clearInterval 不会在 useEffect 中停止我的计数器

IT技术 javascript reactjs react-hooks
2021-05-01 21:41:37

我正在尝试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

2个回答

我想你也不需要使用useState也不useRef挂钩了intervalID像这样useEffectuseEffect钩子的清理函数中声明它但清除间隔

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

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

已解决:正如@derpirscher 指出的,我的 intervalID 只是本地的,我必须将它存储在一个useState钩子中以便以后能够访问它。

  const [intervalID, setInterID] = useState(); // created a useState for intervalID

  useEffect(() => {
    console.log(`isRunning changed to: ${state.isRunning}`);
    console.log(`initial interval is: ${intervalID}`);
    if (state.isRunning === "start") {
      let letintervalID = setInterval(() => {
        console.log(`interval is: ${intervalID}`);
        console.log(`tic toc`);
        dispatch({ type: "tic-toc" });
      }, 1000);
      setInterID(letintervalID); // took letintervalID and stored it in useState intervalID
    } else if (state.isRunning === "stop") {
      console.log("clearInterval stop!");
      clearInterval(intervalID);
    }
  }, [state.isRunning]);