简体   繁体   English

ClearInterval 在 React 中的 useRef 没有按预期工作

[英]ClearInterval is not working as expected with useRef in React

I have created one setInterval which is being called on App Load, Like this我创建了一个在 App Load 上调用的 setInterval,就像这样

  let abc = true;
  let def = true;
  const intervalRef = useRef(null);

  if (abc) {
    intervalRef.current = setInterval(() => {
      console.log("hello console", def);
    }, 2000);
    abc = false;
  }

And trying to stop this interval using clearInterval on some click handler like this -并试图在像这样的一些点击处理程序上使用 clearInterval 来停止这个间隔 -

const clear = () => {
    clearTimeout(intervalRef.current);
    def = false;
    console.log(def);
  };

Issues I am facing right now are -我现在面临的问题是——

  1. Why SetInterval is not stopped on click handler, while I am already cleared it in function?为什么 SetInterval 没有在点击处理程序上停止,而我已经在 function 中清除了它?
  2. Why value of def in not getting updated in setInterval.为什么在 setInterval 中没有更新def的值。

Working example 工作示例

PS: I am new in react, if this is silly mistake forgive me:) PS:我是新手,如果这是愚蠢的错误,请原谅我:)

this is not a silly question, it's something I have seen many people struggling with.这不是一个愚蠢的问题,我看到很多人都在努力解决这个问题。 Let me clarify this:让我澄清一下:

  1. Why SetInterval is not stopped on the click handler, while I am already cleared it in function?为什么SetInterval没有在点击处理程序上停止,而我已经在 function 中清除了它?

This is happening because your component is rendering more than once (so you are creating multiple intervals and only clearing the last one.发生这种情况是因为您的组件不止一次渲染(因此您正在创建多个间隔并且只清除最后一个间隔。

  1. Why the value of def is not getting updated in setInterval .为什么 def 的值没有在setInterval中更新。

There are 2 things to consider here, first, the setInterval callback is not included in react lifecycle so the value does not get updated.这里有两件事要考虑,首先, setInterval回调不包含在反应生命周期中,因此值不会更新。 Last, since you are only changing the value of a variable (but not the component state) the component will not be re-rendered and the code will remain the same.最后,由于您只是更改变量的值(而不是组件状态),因此不会重新渲染组件并且代码将保持不变。

You can find a very good article to deal with intervals in react here -> https://overreacted.io/making-setinterval-declarative-with-react-hooks/您可以在这里找到一篇非常好的文章来处理反应中的间隔 -> https://overreacted.io/making-setinterval-declarative-with-react-hooks/

I also leave you the code here as well as a code snippet link:我还将代码留在这里以及代码片段链接:

import "./styles.css";
import { useEffect, useRef, useState } from "react";
export default function App() {
  const [runInterval, setRunInterval] = useState(true);
  const [counter, setCounter] = useState(0);
  const intervalRef = useRef(null);

  useEffect(() => {
    if (runInterval) {
      intervalRef.current = setInterval(() => {
        setCounter((c) => c + 1);
      }, 1000);
    }

    return () => {
      clearInterval(intervalRef.current);
    }; // clear interval when unmounting the component
  }, [runInterval]);

  const clear = () => {
    setRunInterval(false);
  };

  return (
    <div className="App">
      <h1 onClick={() => clear()}>Click me to Stop Interval</h1>
      <h2>{counter}</h2>
    </div>
  );
}

https://codesandbox.io/s/stoic-elbakyan-u5ezc3?file=/src/App.js:0-734 https://codesandbox.io/s/stoic-elbakyan-u5ezc3?file=/src/App.js:0-734

  1. Why SetInterval is not stopped on click handler, while I am already cleared it in function?为什么 SetInterval 没有在点击处理程序上停止,而我已经在 function 中清除了它?

    One reason is that it should be clearInterval instead of clearTimeout .一个原因是它应该是clearInterval而不是clearTimeout

  2. Why value of def in not getting updated in setInterval.为什么在 setInterval 中没有更新 def 的值。

    You should use useState hook to handle state in a component.您应该使用useState挂钩来处理组件中的 state。 Otherwise abc value gets newly created for each render o(when calling App ) falling back to the initial value.否则,为每个渲染 o(调用App时)重新创建abc值,然后返回到初始值。

You need a useEffect hook to handle it like below.您需要一个useEffect挂钩来处理它,如下所示。 If someone visits this component again and again and did not click clear then it will be a memory leak (since multiple intervals get cleated and never get distroyed).如果有人一次又一次地访问这个组件并且没有单击清除,那么它将是 memory 泄漏(因为多个间隔被清除并且永远不会被破坏)。 Need to handle it clearly when the component gets unmounted as well.当组件被卸载时也需要清楚地处理它。

import { useRef, useEffect } from "react";
export default function App() {
  const intervalRef = useRef(null);

  useEffect(() => {
    const intervalId = setInterval(() => {
      console.log("hello JSG");
    }, 1000);
    // save the interval
    intervalRef.current = intervalId;
    // clear the interval
    return () => {
      clearInterval(intervalRef.current);
    };
  }, []);

  const clear = () => {
    // clear the interval
    clearInterval(intervalRef.current);
  };

  return (
    <div className="App">
      <h1 onClick={() => clear()}>Click me to Stop Interval</h1>
      <h2>Please watch console!</h2>
    </div>
  );
}

Working example:工作示例:

编辑 pedantic-hypatia-uvuonk

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

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