【问题标题】:setInterval() keeps running even after clearing it using clearInterval()即使在使用 clearInterval() 清除 setInterval() 后,它也会继续运行
【发布时间】:2022-01-15 11:59:39
【问题描述】:

我在这里找到的大多数答案是在 useEffect() 的 return 语句中使用 clearInterval()。但是,由于某些原因,它仍然会继续执行。

我还在日志中收到以下警告:-

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in StartTest (at SceneView.tsx:126)

附上代码供参考。

const [connectionInterval, setConnectionInterval] = useState(null);
const [batteryInterval, setBatteryInterval] = useState(null);
const [heartRateInterval, setHeartRateInterval] = useState(null);

useEffect(() => {
    startServices();
    return () => {
      clearServices();
    };
}, []);


const startServices= () => {
    let ctnInt = setInterval(() => checkConnection(), 5000);
    setConnectionInterval(ctnInt);
    let btryInt = setInterval(
      () =>
        Battery(value => {
          setBattery(value);
        }),
      900000,
    );
    setBatteryInterval(btryInt);
    let hrRtInt = setInterval(
      () =>
        HeartRate(
          hr => {
            if (finish) {
              clearInterval(heartRateInterval);
            }
            let rate = Math.round(hr);
            setHeartRate(rate);
          },
          onError => {
            console.log('API ERROR');
          },
        ),
      3000,
    );
    setHeartRateInterval(hrRtInt);
  };


  const clearServices = () => {
    clearInterval(connectionInterval);
    clearInterval(batteryInterval);
    clearInterval(heartRateInterval);
  };```

【问题讨论】:

    标签: javascript reactjs react-native react-hooks


    【解决方案1】:

    您没有将任何 deps 传递给useEffect,因此效果函数永远不会更新,并且在您调用的clearServices 版本中,connectionInterval 和朋友仍然是null。请参阅注释here

    一般来说,我会像这样接近setInterval

    useEffect(() => {
        const intervalFn = () => {
            console.log('interval fired')
        }
        const intervalId = setInterval(intervalFn, 1000)
        return () => {
            clearInterval(intervalId)
        }
    }, [])
    

    (这个版本真的没有依赖,因为一切都在 useEffect 中捕获。但实际上你可能会有一些。)

    【讨论】:

      【解决方案2】:

      几周前我遇到了这个问题,为了解决这个问题,我在清除间隔后设置了一个新状态

      例如。我试图建立一个从 30 到 0 并停在 0 的倒计时。这就是我所做的

      const [timeRemaining, setTimeRemaining] = useState(30);
      
      useEffect(() => {
        let timeLeft = timeRemaining;
        let interval = setInterval(() => {
          if (timeLeft === 0) {
            clearInterval(interval);
            setTimeRemaining(0);
          } else {
            setTimeRemaining((timeLeft -= 1));
          }
        }, 1000);
      }, [timeRemaining]);
      

      在清除间隔后将状态设置为 0 是在 0 处停止倒数计时器的唯一方法

      【讨论】:

        【解决方案3】:

        在useEffect中,你应该在回调函数之后在数组中声明依赖。在上面的代码中,startServices是依赖,因为它是在useEffect之外声明的。

        https://reactjs.org/docs/hooks-reference.html#useeffect

        你可以在链接中了解useEffect。

        【讨论】:

        • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 2021-03-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-14
        相关资源
        最近更新 更多