mirror of https://github.com/buster-so/buster.git
61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
import { useDebounceFn, useMemoizedFn } from 'ahooks';
|
|
import { useEffect, useState, useTransition } from 'react';
|
|
import isEqual from 'lodash/isEqual';
|
|
|
|
interface UseDebounceSearchProps<T> {
|
|
items: T[];
|
|
searchPredicate: (item: T, searchText: string) => boolean;
|
|
debounceTime?: number;
|
|
}
|
|
|
|
export const useDebounceSearch = <T>({
|
|
items,
|
|
searchPredicate,
|
|
debounceTime = 150
|
|
}: UseDebounceSearchProps<T>) => {
|
|
const [isPending, startTransition] = useTransition();
|
|
const [searchText, setSearchText] = useState('');
|
|
const [filteredItems, setFilteredItems] = useState<T[]>(items);
|
|
|
|
const filterItems = useMemoizedFn((text: string): T[] => {
|
|
if (!text) return items;
|
|
const lowerCaseSearchText = text.toLowerCase();
|
|
return items.filter((item) => searchPredicate(item, lowerCaseSearchText));
|
|
});
|
|
|
|
const updateFilteredItems = useMemoizedFn((text: string) => {
|
|
startTransition(() => {
|
|
setFilteredItems(filterItems(text));
|
|
});
|
|
});
|
|
|
|
const { run: debouncedSearch } = useDebounceFn(
|
|
(text: string) => {
|
|
updateFilteredItems(text);
|
|
},
|
|
{ wait: debounceTime }
|
|
);
|
|
|
|
const handleSearchChange = useMemoizedFn((text: string) => {
|
|
setSearchText(text);
|
|
if (!text) {
|
|
updateFilteredItems(text);
|
|
} else {
|
|
debouncedSearch(text);
|
|
}
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (!isEqual(items, filteredItems)) {
|
|
setFilteredItems(items);
|
|
}
|
|
}, [items]);
|
|
|
|
return {
|
|
filteredItems,
|
|
searchText,
|
|
handleSearchChange,
|
|
isPending
|
|
};
|
|
};
|