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?
如果你直接在React组件中使用debounced函数,它将不起作用,因为每个渲染都会创建一个新函数,相反,你可以使用这个
useDebounce
钩子:useRef
确保它与上次提供的函数相同,并且useLayoutEffect
确保在每次渲染时,对函数的引用都会更新。有关这方面的更多信息,请参阅“最新参考”模式反应
我认为与其通过
useEffect
实现去抖,不如将去抖逻辑实现为一个函数。useEffect
当deps
引用的状态改变时执行。也就是说,由于是一个如果只按照执行流程就容易漏掉的逻辑,所以后期维护时很难弄清楚这个useEffect
是从哪一个流程衍生出来的,调试起来也比较困难。示例
自定义反跳
如果您使用
lodash
,则只需导入即可使用它。Lodash Debounce
希望这有帮助:)