import { useEffect, useState } from 'react'; export default function useDebounce(text: string, delay: number) { const [value, setValue] = useState(''); useEffect(() => { const timerId = setTimeout(() => { setValue(text); }, delay); return () => { clearTimeout(timerId); }; }, [text, delay]); return value; }
我曾經製作和使用 useDebounce
鉤子。
但是,在調整大小事件中使用 useDebounce
存在一些問題。
useDebounce hook
必須在元件頂部運行,因為它在內部使用了 useEffect。
但是,調整大小函數設定為在 useEffect 上運行,如下所示。
此外,上面的程式碼將值作為一個因素,但我認為我們需要接收它作為回調才能使用下面的程式碼。
useEffect(() => { const handler = () => { if (liRef.current) setWidth(liRef.current.clientWidth); }; window.addEventListener('resize', handler); return () => window.removeEventListener('resize', handler); }, []);
如何使用上面的程式碼來利用現有的useDebounce?
P粉0984172232024-01-29 11:40:03
如果你直接在React元件中使用debounced函數,它將不起作用,因為每個渲染都會建立一個新函數,相反,你可以使用這個useDebounce
鉤子:
function useDebounce(callback, delay) { const callbackRef = React.useRef(callback) React.useLayoutEffect(() => { callbackRef.current = callback }) return React.useMemo( () => debounce((...args) => callbackRef.current(...args), delay), [delay], ) }
useRef
確保它與上次提供的函數相同,並且 useLayoutEffect
確保在每次渲染時,對函數的引用都會更新。
有關這方面的更多信息,請參閱“最新參考”模式反應
P粉8940084902024-01-29 09:59:42
我認為與其透過useEffect
實現去抖,不如將去抖邏輯實作為一個函數。
useEffect
當deps
引用的狀態改變時執行。也就是說,由於是一個如果只按照執行流程就容易漏掉的邏輯,所以後期維護時很難弄清楚這個useEffect
是從哪一個流程衍生出來的,調試起來也比較困難。
範例
自訂反跳
function debounce(func, timeout = 300) { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, timeout); }; }
function saveInput() { console.log('Saving data'); } const processChange = debounce(() => saveInput());
如果您使用lodash
,則只需匯入即可使用它。
Lodash Debounce
import { debounce } from 'lodash';
const debounceOnChange = debounce(() => { console.log("This is a debounce function"); }, 500);
希望這有幫助:)