Javascript clearInterval未停止使用中的计数器

Javascript clearInterval未停止使用中的计数器,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我试图在useffectReact钩子中使用setInterval和clearInterval。计时器按预期启动,但不会停止。 我正在将setInterval分配给intervalID然后调用clearInterval(intervalID) 完整代码:已解决:正如@derpirscher指出的,我的intervalID只是本地的,我必须将它存储在useState钩子中,以便以后能够访问它 const [intervalID, setInterID] = useState(); // cre

我试图在
useffect
React钩子中使用
setInterval
clearInterval
。计时器按预期启动,但不会停止。 我正在将
setInterval
分配给
intervalID
然后调用
clearInterval(intervalID)


完整代码:

已解决:正如@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]);

我认为您不需要使用
useState
useRef
钩子来实现
intervalID
。在
useffect
之外声明它,但是像这样清除
useffect
钩子的清理函数中的间隔

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

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

在间隔开始后,该代码如何到达else分支?如果您再次调用回调,它将无法访问以前存储的intervalid,因为它是callback@derpirscher我应该使用useState还是useReducer来存储intervalID?成功了!我使用
useState
来存储intervalID。谢谢我没有使用react的经验,所以我不知道useState或useReducer是什么,但您必须将intervalid存储在这个回调之外,以便以后能够再次使用它。我对挂钩没有太多经验,但我非常确定这是在函数组件中保存类似内容的正确方法。(在类组件中,您只需要使用实例属性。)所以这就是清理!我一直在读,但直到你的评论我才明白!谢谢你,它工作得很好!是的,isRunning是从我的
useReducer
中获得的,在对布尔值进行了多次不顾一切的尝试后,我将其作为一个字符串在
的“开始”
的“停止”
之间切换(布尔值不是问题,但我必须尝试一些东西)。现在我把它移回了布尔值。更新:出现了这个错误,结果是最好保持
let intervalID内部
useffect()
而且效果很好<每次渲染后,从内部对“intervalID”变量的代码>指定都将丢失。要随时间保留该值,请将其存储在useRef挂钩中,并将可变值保留在“.current”属性中。否则,您可以将此变量直接移动到useEffect react hooks/deps内部
@VictorLazaro,只要您不需要从组件中的任何其他位置清除间隔,就可以将其保持在本地运行。@VictorLazaro您的意思是警告而不是错误,对吗?它是否丢失其值无关紧要,因为如果组件重新加载,则意味着
isRunning
状态变量已更改,这意味着如果
isRunning
为true,则将再次设置
intervalID
,如果
isRunning
为false,则不会分配它。将其保持在外部可使您从组件中的任何位置清除间隔。明白。对于这一点,我需要它重置为不计数时,状态改变回来,使有线完美。但我明白你把它留在外面的意思。
let intervalID;
useEffect(() => {
    if (isRunning) {
      intervalID = setInterval(() => {
        dispatch({ type: "tic-toc" });
      }, 1000);
    }
      return () => clearInterval(intervalID);
  }, [isRunning]);