我需要在 React 中的自定义钩子中创建一个事件处理程序,并且我希望事件处理函数在渲染之间引用相等。原因(是的,我确实知道如何做到这一点,但我想理解)。我可以如下使用 useCallback 来确保 eventListener 在每个渲染上引用相等,只需不提及它在依赖项中关闭的变量(如下所示),否则会导致问题即使它从未传递给子组件,所以我不这样做不需要它改变值来触发重新渲染?
如果不是,我怎样才能实现这一目标?如果我可以假设延迟和 fn 不改变(除了它可能是参考),这有什么关系吗?
export const useVisibleInterval = (fn, delay = 300000) => {
const interval_id = useRef(null)
const handleVisibilityChange = useCallback(() => {
if (document.hidden || interval_id.current) return
interval_id.current = setInterval(fn, delay)
fn()
}, [])
const clearInt = () => {
if (!interval_id.current) return
clearInterval(interval_id.current)
interval_id.current = null
}
const interval_run = () => {
if (document.hidden) {
document.addEventListener("visibilitychange", handleVisibilityChange)
clearInt()
} else fn()
}
const teardown = () => {
document.removeEventListener("visibilitychange", handleVisibilityChange)
clearInt()
}
useEffect(() => {
interval_id.current = setInterval(interval_run, delay)
return teardown
}, [])
}
在一个非常高的层面上,我想了解 useCallback 的依赖项的作用。他们只是为了强制引用不平等,以便依赖它的子组件重新渲染吗?或者 React 是否会记住函数执行的结果,因此如果不包含依赖项会导致结果过时?
根据pilchard的评论,我已经找到了答案(而且我是个白痴)。
问题仅仅是当使用新参数调用函数时更新哪些值。引用不需要需要在useCallback的依赖项中列出,所以我可以做到这一点的方法就是简单地用采用这些值的引用替换fn和delay,例如,
ref_fn = useRef(fn)
useEffect(()=> {ref_fn.current = fn}, [fn]}
同样用于延迟(或将它们填充到相同的引用中)。但是,事实证明我什至不需要 useCallback 和引用相等,上面的代码反映了我当时的深深困惑,应该被忽略。