事件侦听器的 React useEffect 清理

React useEffect cleanup for event listener

在我的 React 组件中,我有一个针对 beforeunload 的事件处理。我想在我的 useEffect return 中清理它。下面的代码是做同样事情的正确方法还是有更好的方法?

useEffect(() => {
    if (Object.keys(someKey).length > 0) {
        function callSvc(urls) {
        }
        callSvc(urls);
        
        const intV = setInterval(callSvc, interval, urls);
        window.addEventListener("beforeunload", function() {clearInterval(intV)});

        return () => {
            //window.removeEventListener("beforeunload", function() {clearInterval(intV)});
        }
    }
}, [someKey])

更新代码

useEffect(() => {
    if (Object.keys(someKey).length > 0) {
        const intV = setInterval(callSvc, interval, urls);
        function clearTimer() {
            clearInterval(intV)
        }
        window.addEventListener("beforeunload", clearTimer);
        return () => {
            window.removeEventListener("beforeunload", clearTimer);
        }
    }
}, [someKey])

这是 return if-block 中函数的正确方法,useEffect() 只有在 if-statement 中的条件为 [=15= 时才会 clean-up ],但是当没有要添加的侦听器时,不需要在 useEffect() 函数的顶层 clean-up。

  useEffect(()=>{
    let getThere = someBoolean
    if (getThere) {
      console.log("Listener Added.")
      return () => {
        console.log("Listener Removed. (Inside If statement)")
      }
    }
    return () => {
      console.log("No Listener to Remove.")
    }
  },[])

然后通过mount/unmount测试切换页面(我目前使用的是react-router-dom)然后观察控制台。

如果条件是 true

Listener Added.
Listener Removed. (Inside If statement)

如果条件是false

No Listener to Remove.

如果布尔值是 true 函数将 return 仅 if-block 内部的函数,不会流入外部 return,除了布尔值是 false,代码将转到外层的return。

Is the below code the correct way of doing the same or is there any better way ?

您的代码存在一个关键问题:只有当您向 removeEventListener 传递与传递给 addEventListener 的函数完全相同时,才能删除事件处理程序。但就目前而言,您正在传递两个不同的功能。这很容易解决,只需将函数存储在变量中并在 addEventListenerremoveEventListener.

中引用该变量

但是,我怀疑 beforeunload 事件处理程序是否必要。当页面关闭时,任何 JS 代码都会停止 运行。我认为当效果 re-runs 时停止间隔更重要,否则每当效果再次运行时,您将开始一个新的间隔,从而导致多个并行间隔:

useEffect(() => {
    if (Object.keys(someKey).length > 0) {
        function callSvc(urls) {
        }
        callSvc(urls);
        
        const intV = setInterval(callSvc, interval, urls);
        return () => {
            clearInterval(intV)
        }
    }
}, [someKey])