如何在 React 功能组件中正确设置 setInterval 计时器? [英] How to Setup a setInterval Timer Properly in a React Functional Component?

查看:70
本文介绍了如何在 React 功能组件中正确设置 setInterval 计时器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始学习 React,我正在看一个关于状态和钩子的教程.它只是处理每 1000 毫秒更新一次时间(或者我认为是这样).

I have just started learning react and I was watching a tutorial which deals with state and hooks. It just deals with updating time every 1000 milliseconds (or so I thought).

import React from "react";
let count = 0;

function App() {
  const now = new Date().toLocaleTimeString();
  let [time, setTime] = React.useState(now);


  function updateTime(){
    const newTime = new Date().toLocaleTimeString();
    setTime(newTime);
    count++;
    console.log(count);
    console.log(new Date().getMilliseconds());
  }

  setInterval(updateTime, 1000);


  return (
    <div className="container">
      <h1>{time}</h1>
      <button onClick = {updateTime}>time</button>
    </div>
  );
}

export default App;

);}导出默认应用程序;

The purpose of the tutorial was just a simple example on how to update time, but what I noticed is that it is updated multiple times (in bursts) every 1000 milliseconds. I am suspecting that each time change to a hook happens new component is rendered but the old component is still there updating and spawning more components resulting in what seems like exponential growth of calls every 1000 milliseconds.

本教程的目的只是一个关于如何更新时间的简单示例,但我注意到它每 1000 毫秒更新多次(以突发方式).我怀疑每次对钩子进行更改时都会呈现新组件,但旧组件仍在那里更新并产生更多组件,导致每 1000 毫秒的调用呈指数增长.

I am very curious what is happening here? How would I go about lets say having a simple counter that updates every 1000 milliseconds? setTime(count) obviously does not work

我很好奇这里发生了什么?我将如何去做让我们说有一个每 1000 毫秒更新一次的简单计数器?setTime(count) 显然不起作用

解决方案

推荐答案

问题:在您当前的实现中,setInterval 将在每次组件渲染时调用(即,也会在时间状态已设置)并将创建一个新的间隔 - 这产生了这种指数增长"如您的控制台所示.

As explained in the comments section: useEffect would be the best way to handle this scenario when dealing with functional components in React. Take a look at my example below. useEffect here will only run after the initial component render (when the component mounts).

如评论部分所述:useEffect在 React 中处理功能组件时,这将是处理这种情况的最佳方式.看看我下面的例子.useEffect 这里只会在初始组件渲染后运行(当组件挂载时).

React.useEffect(() => { console.log(`initializing interval`); const interval = setInterval(() => { updateTime(); }, 1000); return () => { console.log(`clearing interval`); clearInterval(interval); }; }, []); // has no dependency - this will be called on-component-mount


<块引用>

如果你想运行一个效果并且只清理一次(在安装和unmount),您可以传递一个空数组 ([]) 作为第二个参数.这告诉 React 你的效果不依赖于来自 props 的任何值或状态,所以它永远不需要重新运行.

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.

在您的场景中,这是空数组作为第二个参数"的完美用法;因为您只需要在安装组件时设置间隔并在卸载时清除间隔.看看 useEffect 返回的函数.这是我们的清理功能,将在组件卸载时运行.这将清洁"或者在这种情况下,当组件不再使用时清除间隔.

In your scenario, this is a perfect usage of the "empty array as a second argument" since you would only need to set the interval when the component is mounted and clear the interval when it unmounts. Take a look at the function that the useEffect returns as well. This is our cleanup function that will run when the component unmounts. This will "clean" or in this case, clear the interval when the component is no longer in use.

我编写了一个小应用程序来演示我在此答案中涵盖的所有内容:https://codesandbox.io/s/so-react-useeffect-component-clean-up-rgxm0?file=/src/App.js

I've written a small application that demonstrates everything I've covered in this answer: https://codesandbox.io/s/so-react-useeffect-component-clean-up-rgxm0?file=/src/App.js

我已经合并了一个小的路由功能,以便卸载"可以观察到组件.

I've incorporated a small routing functionality so that "unmounting" of the component can be observed.

我的旧答案(不推荐):

My old answer (not recommended):

每次组件重新渲染时都会创建一个新的时间间隔,这就是为时间设置新状态时发生的情况.我要做的是在设置新间隔之前清除上一个间隔(clearInterval)

A new interval is created everytime the component re-renders, which is what happens when you set the new state for time. What I would do is clear the previous interval (clearInterval) before setting up a new one

try {
  clearInterval(window.interval)
} catch (e) {
  console.log(`interval not initialized yet`);
}

window.interval = setInterval(updateTime, 1000);

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

这篇关于如何在 React 功能组件中正确设置 setInterval 计时器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆