简体   繁体   English

React useEffect 钩子没有清除间隔

[英]React useEffect hook doesn't clear interval

I'm trying to build a simple count down timer using react hooks to count down 3 seconds.我正在尝试使用反应挂钩构建一个简单的倒数计时器来倒计时 3 秒。 But after 3 seconds UI stop rendering but in console.log I can still is prints out every second.但是 3 秒后 UI 停止渲染但在 console.log 中我仍然可以每秒打印一次。 Why is the second array parameter in useEffect doesn't prevent this from happening?为什么 useEffect 中的第二个数组参数不能阻止这种情况的发生?

code sandbox 代码沙箱

function CounterGame() {
  const [timeout, setTimeout] = React.useState(3);

  React.useEffect(() => {
    let id = window.setInterval(() => {
      if (timeout > 0) {
        setTimeout(x => x - 1 );
      }
      // this line keep executing even it timeout reach 0
      console.log("in setInterval", timeout);
    }, 1000)

    return () => {
      window.clearInterval(id);
    }
  }, [timeout])
  return (
    <div className="App">
      See instructions.
      <h1>{timeout} seconds</h1>
      {!timeout && <button>Click</button>}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<CounterGame />, rootElement);

This may works for you:这可能对你有用:

clearIntervel when timeOut is zero by adding condition in useEffect通过在 useEffect 中添加条件,在 timeOut 为零时清除间隔

React.useEffect(() => {
      let id = window.setInterval(() => {
        if (timeout > 0) {
          setTimeout(x => x - 1 );
        }

    //clearIntervel here
        if(timeout == 0){
            window.clearInterval(id);
        }

        // this line keep executing even it timeout reach 0
        console.log("in setInterval", timeout);
      }, 1000)
  
      return () => {
        window.clearInterval(id);
      }
    }, [timeout])

According to theReact docs :根据React 文档

This is why React also cleans up effects from the previous render before running the effects next time.这就是为什么 React 还会在下次运行效果之前清理上一次渲染的效果。

Based on this, I believe that the cleanup function is not run until the next iteration of the useEffect .基于此,我相信清理 function 直到useEffect的下一次迭代才会运行。 In your example, after timeout hits 0, the useEffect will run 1 more time, setting up a new interval, but because timeout is 0, it will not update the state, so the useEffect won't be called on the next render.在您的示例中, timeout达到 0 后, useEffect将再运行 1 次,设置新的间隔,但由于timeout为 0,它不会更新 state,因此不会在下一次渲染时调用useEffect That means the cleanup function never gets called for that last iteration.这意味着最后一次迭代永远不会调用清理 function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM