Core: Support debounce value on algolia search client

This commit is contained in:
fuma-nama
2024-08-04 00:42:04 +08:00
parent b109e44715
commit 2cf65f6c1d
5 changed files with 39 additions and 22 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-core': patch
---
Support debounce value on algolia search client
-1
View File
@@ -16,5 +16,4 @@ async function main() {
await main().catch((e) => {
console.error('Failed to run post build script', e);
throw e;
});
+13 -4
View File
@@ -3,6 +3,7 @@ import type { SearchIndex } from 'algoliasearch/lite';
import { useState } from 'react';
import useSWR, { type SWRResponse } from 'swr';
import type { SortedResult } from '@/search/shared';
import { useDebounce } from '@/utils/use-debounce';
import type { BaseIndex } from './server';
export interface Options extends SearchOptions {
@@ -12,6 +13,13 @@ export interface Options extends SearchOptions {
* @defaultValue true
*/
allowEmpty?: boolean;
/**
* Delay to debounce (in ms)
*
* @defaultValue 300
*/
delay?: number;
}
export function groupResults(hits: Hit<BaseIndex>[]): SortedResult[] {
@@ -77,16 +85,17 @@ interface UseAlgoliaSearch {
export function useAlgoliaSearch(
index: SearchIndex,
{ allowEmpty = true, ...options }: Options = {},
{ allowEmpty = true, delay = 150, ...options }: Options = {},
): UseAlgoliaSearch {
const [search, setSearch] = useState('');
const debouncedValue = useDebounce(search, delay);
const query: UseAlgoliaSearch['query'] = useSWR(
['algolia-search', search, allowEmpty, options],
['algolia-search', debouncedValue, allowEmpty, options],
async () => {
if (allowEmpty && search.length === 0) return 'empty';
if (allowEmpty && debouncedValue.length === 0) return 'empty';
return searchDocs(index, search, options);
return searchDocs(index, debouncedValue, options);
},
{
keepPreviousData: true,
+2 -17
View File
@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react';
import { useState } from 'react';
import useSWR, { type SWRResponse } from 'swr';
import { useDebounce } from '@/utils/use-debounce';
import type { SortedResult } from './shared';
interface UseDocsSearch {
@@ -56,19 +57,3 @@ export function useDocsSearch(
return { search, setSearch, query };
}
function useDebounce<T>(value: T, delayMs = 1000): T {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delayMs);
return () => {
clearTimeout(handler);
};
}, [value, delayMs]);
return debouncedValue;
}
+19
View File
@@ -0,0 +1,19 @@
import { useRef, useState } from 'react';
export function useDebounce<T>(value: T, delayMs = 1000): T {
const [debouncedValue, setDebouncedValue] = useState(value);
const timer = useRef<{ value: T; handler: number }>();
if (delayMs === 0) return value;
if (value !== debouncedValue && timer.current?.value !== value) {
if (timer.current) clearTimeout(timer.current.handler);
const handler = window.setTimeout(() => {
setDebouncedValue(value);
}, delayMs);
timer.current = { value, handler };
}
return debouncedValue;
}