我在 React 中创建了一个自定义钩子,它为给定的一组事件设置了一个事件侦听器。存在一组默认事件,并且此自定义钩子的使用者预计不会在大多数用例中自定义这些事件。通常,我希望在安装组件时添加事件侦听器,并在卸载组件时将其删除。但是,遵循钩子(和eslint(react-hooks/exhaustive-deps)
lint 规则)的原则,我希望优雅地处理对要监视的事件列表的更改。使用 React 钩子实现这一目标的最惯用的方法是什么?
假设我只想删除所有事件侦听器并在事件列表更改时重新添加它们,我可以尝试以下操作:
const useEventWatcher = (
interval = 5000,
events = ['mousemove', 'keydown', 'wheel']
) => {
const timerIdRef = useRef();
useEffect(() => {
const resetInterval = () => {
if (timerIdRef.current) {
clearInterval(timerIdRef.current);
}
timerIdRef.current = setInterval(() => {
console.log(`${interval} milliseconds passed with no ${events.join(', ')} events!`);
}, interval)
};
events.forEach(event => window.addEventListener(event, resetInterval));
// Don't want to miss the first time the interval passes without
// the given events triggering (cannot run the effect after every render due to this!)
resetInterval();
return () => {
events.forEach(event => window.removeEventListener(event, resetInterval));
};
}, [events, interval]);
}
不幸的是,这将无法按预期运行。请注意,我想为events
参数提供默认值。使用当前方法执行此操作意味着events
每次自定义挂钩运行时都指向不同的引用,这意味着效果每次也会运行(由于浅层依赖比较)。理想情况下,我想要一种使效果取决于数组内容而不是引用的方法。实现这一目标的最佳方法是什么?