From ad90f8d6995ed0a91a27e55186b3e8cdce8091fa Mon Sep 17 00:00:00 2001 From: skinmaker1345 Date: Mon, 4 Mar 2024 23:34:36 +0900 Subject: [PATCH] perf: optimize search --- components/Search.tsx | 55 ++++++++++++++++++++++++++----------------- utils/Query.ts | 12 +++++----- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/components/Search.tsx b/components/Search.tsx index 9ffbb586e6..e1e6b6f5a3 100644 --- a/components/Search.tsx +++ b/components/Search.tsx @@ -19,7 +19,7 @@ const Search: React.FC = () => { const [recentSearch, setRecentSearch] = useState([]) const [data, setData] = useState>(null) const [loading, setLoading] = useState(false) - const [abortControl, setAbortControl] = useState(new AbortController()) + const abortController = useRef(null) const [hidden, setHidden] = useState(true) useEffect(() => { setQuery('') @@ -32,26 +32,37 @@ const Search: React.FC = () => { } }, [router]) useOutsideClick(ref, () => setHidden(true)) - const SearchResults = async (value: string) => { - setData(null) - setQuery(value) - try { - abortControl.abort() - } catch (e) { - return null + + useEffect(() => { + if (query.length < 2) { + setData(null) + return } - const controller = new AbortController() - setAbortControl(controller) - if (value.length > 1) setLoading(true) - const res = await Fetch(`/search/all?q=${encodeURIComponent(value)}`, { - signal: controller.signal, - }).catch((e) => { - if (e.name !== 'AbortError') throw e - else return - }) - setData(res || {}) - setLoading(false) - } + const timeout = setTimeout(async () => { + setData(null) + try { + if (abortController.current) { + abortController.current.abort() + } + } catch (e) { + return null + } + abortController.current = new AbortController() + if (query.length > 1) setLoading(true) + const res = await Fetch(`/search/all?q=${encodeURIComponent(query)}`, { + signal: abortController.current.signal, + }).catch((e) => { + if (e.name !== 'AbortError') throw e + else return + }) + abortController.current = null + setData(res || {}) + setLoading(false) + }, 1000) + return () => { + clearTimeout(timeout) + } + }, [query]) const onSubmit = () => { if (query.length < 2) return @@ -93,7 +104,7 @@ const Search: React.FC = () => { placeholder='검색...' value={query} onChange={(e) => { - SearchResults(e.target.value) + setQuery(e.target.value) }} onKeyDown={(e) => { if (e.key === 'Enter') { @@ -208,7 +219,7 @@ const Search: React.FC = () => { ))} ) - ) : query.length < 3 ? ( + ) : query.length < 2 ? ( '최소 2글자 이상 입력해주세요.' ) : ( '검색어를 입력해주세요.' diff --git a/utils/Query.ts b/utils/Query.ts index edb0e504b8..61c3d0f6b3 100644 --- a/utils/Query.ts +++ b/utils/Query.ts @@ -301,8 +301,8 @@ async function getBotList(type: ListType, page = 1, query?: string): Promise await getBot(el.id)))).map((r) => ({ ...r })), currentPage: page, - totalPage: Math.ceil(Number(count) / 16), + totalPage: Math.ceil(Number(count) / 8), } } @@ -402,12 +402,12 @@ async function getServerList(type: ListType, page = 1, query?: string): Promise< )[0][0]['count(*)'] res = ( await knex.raw( - 'SELECT id, votes, MATCH(`name`, `intro`, `desc`) AGAINST(? in boolean mode) as relevance FROM servers WHERE `state` != "blocked" AND last_updated >= ? AND MATCH(`name`, `intro`, `desc`) AGAINST(? in boolean mode) ORDER BY relevance DESC, votes DESC LIMIT 16 OFFSET ?', + 'SELECT id, votes, MATCH(`name`, `intro`, `desc`) AGAINST(? in boolean mode) as relevance FROM servers WHERE `state` != "blocked" AND last_updated >= ? AND MATCH(`name`, `intro`, `desc`) AGAINST(? in boolean mode) ORDER BY relevance DESC, votes DESC LIMIT 8 OFFSET ?', [ decodeURI(query) + '*', new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), decodeURI(query) + '*', - ((page ? Number(page) : 1) - 1) * 16, + ((page ? Number(page) : 1) - 1) * 8, ] ) )[0] @@ -419,7 +419,7 @@ async function getServerList(type: ListType, page = 1, query?: string): Promise< type, data: (await Promise.all(res.map(async (el) => await getServer(el.id)))).map((r) => ({ ...r })), currentPage: page, - totalPage: Math.ceil(Number(count) / 16), + totalPage: Math.ceil(Number(count) / 8), } }