Мне никогда не нравится useCallback
, это довольно запутанный крючок, и я всегда использую вместо него useMemo
, поскольку он полностью покрывает то, что может useCallback
(но не наоборот).
function SearchBar() {
const [searchValue, setSearchValue] = useState("");
const handleSearchFieldChange = ((value:string) => {
setSearchValue(value);
});
const debounceLoadData = useMemo(() => debounce(fetchData, 1000), []);
/**
* the equivalent of useCallback should be:
*
* const debounceLoadData = useCallback(debounce(fetchData, 1000), []);
*
* But I really advice against it!
* There's unnecessary function invocation compared to useMemo.
*/
useEffect(() => {
debounceLoadData(searchValue); // <- you should pass in arg
console.log({searchValue})
}, [searchValue]);
// ...
}
Тем не менее, для вашего случая я не думаю, что использование loda sh debounce - лучшее решение.
Существует скрытый риск того, что окончательный вызов эффекта fetchData
произойдет ПОСЛЕ размонтирования вашего компонента. И если fetchData
содержит некоторый лог c мутации состояния, это вызовет ошибку «Невозможно вызвать setState (или forceUpdate) на размонтированном компоненте». что не деструктивно, но и не оптимально.
Я предлагаю вручную отменить вызов, используя setTimeout/clearTimeout
. Это довольно просто:
useEffect(() => {
const timeoutId = setTimeout(() => fetchData(searchValue), 1000)
return () => clearTimeout(timeoutId)
}, [searchValue])