首页 > 解决方案 > clearInterval 没有在 useEffect 中停止我的计数器

问题描述

我正在尝试在React 钩子中使用 asetInterval和 a 。计时器按预期启动,但不会停止。我分配给然后打电话clearIntervaluseEffectsetIntervalintervalIDclearInterval(intervalID)

  useEffect(() => {
    console.log(`isRunning changed to: ${state.isRunning}`); //isRunning changed to: start
    let intervalID;
    console.log(`initial interval is: ${intervalID}`); // initial interval is: undefined
    if (state.isRunning === "start") {
      intervalID = setInterval(() => {
        console.log(`interval is: ${intervalID}`); // interval is: 7
        console.log(`tic toc`);
        dispatch({ type: "tic-toc" });
      }, 1000);
    } else if (state.isRunning === "stop") {
      console.log("clearInterval stop!"); // when I set isRunning to stop, this log shows in the console, but the next line doesn't stop the timer.
      clearInterval(intervalID);
    }
  }, [state.isRunning]);

完整代码:https ://github.com/LazaroFilm/pomodoro

标签: javascriptreactjsreact-hooks

解决方案


我认为您既不需要使用useState也不需要useRefintervalID. 像这样在钩子的清理函数中声明它useEffect但清除间隔useEffect

let intervalID;
useEffect(() => {
    if (isRunning) {
      intervalID = setInterval(() => {
        dispatch({ type: "tic-toc" });
      }, 1000);
    }
      return () => clearInterval(intervalID);
  }, [isRunning]);

每当isRunning发生更改时,组件将卸载,并且将执行清理功能。因此,如果isRunning已更改为,false则计时器应在卸载时停止,并且当再次安装时,将不满足 if 语句中的条件以运行 setInterval,因此计时器保持停止状态。在我的代码中,我假设isRunning它是布尔值(这是我更喜欢的方式),并假设它是“解构”的state,我假设它来自useReducer钩子。


推荐阅读