11'use client' ;
22import Image from 'next/image' ;
3- import { useState , useEffect } from 'react' ;
3+ import { useState , useEffect , useMemo } from 'react' ;
44import { Search , UserCircle } from 'lucide-react' ;
55import { useFollowUser } from '@/hooks/useSocialFeatures' ;
66import { apiClient } from '@/lib/api' ;
@@ -40,11 +40,10 @@ function UserRow({ user }: { user: SocialUser }) {
4040 < button
4141 onClick = { isFollowing ? unfollow : follow }
4242 disabled = { loading }
43- className = { `px-3 py-1 rounded-lg text-xs font-medium transition-colors disabled:opacity-50 ${
44- isFollowing
45- ? 'border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800'
46- : 'bg-blue-600 text-white hover:bg-blue-500'
47- } `}
43+ className = { `px-3 py-1 rounded-lg text-xs font-medium transition-colors disabled:opacity-50 ${ isFollowing
44+ ? 'border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800'
45+ : 'bg-blue-600 text-white hover:bg-blue-500'
46+ } `}
4847 >
4948 { isFollowing ? 'Unfollow' : 'Follow' }
5049 </ button >
@@ -56,8 +55,18 @@ export default function FollowingSystem({ userId }: FollowingSystemProps) {
5655 const [ tab , setTab ] = useState < ListTab > ( 'followers' ) ;
5756 const [ users , setUsers ] = useState < SocialUser [ ] > ( [ ] ) ;
5857 const [ query , setQuery ] = useState ( '' ) ;
58+ const [ debouncedQuery , setDebouncedQuery ] = useState ( '' ) ;
5959 const [ loading , setLoading ] = useState ( false ) ;
6060
61+ // Debounce the search input query by 300ms
62+ useEffect ( ( ) => {
63+ const timer = setTimeout ( ( ) => {
64+ setDebouncedQuery ( query ) ;
65+ } , 300 ) ;
66+
67+ return ( ) => clearTimeout ( timer ) ;
68+ } , [ query ] ) ;
69+
6170 useEffect ( ( ) => {
6271 setLoading ( true ) ;
6372 apiClient
@@ -67,7 +76,11 @@ export default function FollowingSystem({ userId }: FollowingSystemProps) {
6776 . finally ( ( ) => setLoading ( false ) ) ;
6877 } , [ tab , userId ] ) ;
6978
70- const filtered = users . filter ( ( u ) => u . name . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ) ;
79+ // Memoize the filtered user results based on the debounced query
80+ const filtered = useMemo ( ( ) => {
81+ const lowercaseQuery = debouncedQuery . toLowerCase ( ) ;
82+ return users . filter ( ( u ) => u . name . toLowerCase ( ) . includes ( lowercaseQuery ) ) ;
83+ } , [ users , debouncedQuery ] ) ;
7184
7285 return (
7386 < div className = "bg-white dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-700" >
@@ -77,11 +90,10 @@ export default function FollowingSystem({ userId }: FollowingSystemProps) {
7790 < button
7891 key = { t }
7992 onClick = { ( ) => setTab ( t ) }
80- className = { `flex-1 py-3 text-sm font-medium capitalize transition-colors ${
81- tab === t
82- ? 'border-b-2 border-blue-600 text-blue-600 dark:text-blue-400'
83- : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'
84- } `}
93+ className = { `flex-1 py-3 text-sm font-medium capitalize transition-colors ${ tab === t
94+ ? 'border-b-2 border-blue-600 text-blue-600 dark:text-blue-400'
95+ : 'text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'
96+ } `}
8597 >
8698 { t }
8799 </ button >
@@ -118,4 +130,4 @@ export default function FollowingSystem({ userId }: FollowingSystemProps) {
118130 </ div >
119131 </ div >
120132 ) ;
121- }
133+ }
0 commit comments