react hooks:如何处理 co-dependent useCallbacks



react hook 的 linter 喜欢对 DependencyList 严格要求。这会导致以下损坏的情况,其中 2 个事件处理程序相互依赖。由于函数是向addEventListener注册的,我知道如果它们发生变化,它会导致内存泄漏,所以简单的事情就是清空依赖项列表——但是在玩 linter 规则时处理这个问题的正确方法是什么?

const onMouseMove = useCallback((e) => {
  if (!isSwipe(e)) {
    onMouseUp(e)
  }
}, [onMouseUp])
const onMouseUp = useCallback((e) => {
  document.removeEventListener('mousemove', onMouseMove)
}, [onMouseMove])

useCallback本质上是useMemo的一个版本,专门用于记忆函数。 如果两个函数是相互依赖的,不能和useCallback分开记忆,可以和useMemo一起记忆:

const { onMouseMove, onMouseUp } = useMemo(() => {
    const onMouseMove = (e) => {
        if (!isSwipe(e)) {
            onMouseUp(e)
        }
    };
    const onMouseUp = (e) => {
        document.removeEventListener('mousemove', onMouseMove)
    }
    return { onMouseMove, onMouseUp };
}, [/* shared deps*/]);

这是我用来一起记忆函数的一般模式,我认为这是对一般问题的最简单的答案。 但是我不确定,查看此处的实际代码,这是最好的方法 - 如果onMouseMove是与由于useMemo重新计算而注册的函数不同的函数,则该removeEventListener可能不起作用。 在实践中,可能更像是一种useEffect用例。

经过一些研究,看起来(useCallback((在实践中经常失效(的解决方案也可以解决这个问题。一般的想法是记住一个指向指向最新函数的 ref 的函数。

这是一个肮脏的黑客,也可能在并发模式下导致问题,但就目前而言,这是Facebook的建议:如何从useCallback读取经常变化的值

const useEventCallback = (fn) => {
    const ref = useRef(fn)
    useEffect(() => {
        ref.current = fn
    })
    return useCallback((...args) => {
        ref.current(...args)
    }, [ref])
}
const onMouseMove = useEventCallback((e) => {
  if (!isSwipe(e)) {
    onMouseUp(e)
  }
})
const onMouseUp = useEventCallback((e) => {
  document.removeEventListener('mousemove', onMouseMove)
})

相关内容

  • 没有找到相关文章

最新更新