简体   繁体   English

React 组件意外反应

[英]React component reacts unexpectedly

The following is a simple react component:下面是一个简单的反应组件:

import React from "react";
import { useState } from "react";


export default function Comp() {

  let [count, setCount] = useState(1);

  function countUp(){
    setCount(count + 1);
  }

  setInterval(countUp, 1000);

  return <h2>{count}</h2>
}

I expected the counter to go up every second But for some reason, after ten - twenty seconds something starts to go wrong我预计计数器每秒都会上升但是出于某种原因,十到二十秒后开始出现问题

See here: https://stackblitz.com/edit/react-az7qgn?file=src/comp.jsx见这里: https : //stackblitz.com/edit/react-az7qgn?file=src/comp.jsx

Can anyone explain this?谁能解释一下?

You should use useEffect hook to set up that properly.您应该使用useEffect钩子来正确设置。 I can provide an example.我可以提供一个例子。

import React, { useState, useEffect } from "react";


export default function Comp() {
  const [count, setCount] = useState(1);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(state => state + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, []);

  return <h2>{count}</h2>
}

A couple of notes.一些注意事项。

In general, you would prefer const over let , but this is mandatory when destructuring things coming from React.一般来说,你更喜欢const不是let ,但在解构来自 React 的东西时这是强制性的。

I suggest to read Using the Effect Hook on React docs to more information about useEffect .我建议阅读Using the Effect Hook on React 文档以了解有关useEffect更多信息。

Basically, useEffect allows you to achieve similar results to componentDidMount and componentDidUpdate lifecycle methods for class components.基本上, useEffect允许您获得与类组件的componentDidMountcomponentDidUpdate生命周期方法类似的结果。 Also, in this specific case, by returning a function in useEffect callback, we make sure to clear the scheduled callback when it's time to clean up, which means after each run.此外,在这种特定情况下,通过在useEffect回调中返回一个函数,我们确保在需要清理时清除计划的回调,这意味着在每次运行之后。 This actually avoids the mess of stacking many setInterval on top of each other.这实际上避免了将许多setInterval堆叠在一起的混乱情况。

Also, when you setCount it's preferable to get the previous state by using the callback form, because that will be always up-to-date.此外,当您setCount ,最好使用回调表单获取先前的状态,因为这将始终是最新的。

When calling setInterval(), it returns an interval id.当调用 setInterval() 时,它返回一个间隔 id。 Your code is not saving the variable, and thus you cannot reset it.您的代码没有保存变量,因此您无法重置它。 On smaller iterations, you will not see the changes for every iteration.在较小的迭代中,您不会看到每次迭代的变化。 But, as the number of times that setInterval() is called increases from 0 to N, more timers are being initiated, and you will rapidly see flashes of numbers as they increase, because every interval is changing the state of count .但是,随着 setInterval() 被调用的次数从 0 增加到 N,更多的计时器被启动,随着数字的增加,你会很快看到数字闪烁,因为每个间隔都在改变count的状态。

In other words, you are creating more and more timers as time goes on, rather than creating timers for one-time use.换句话说,随着时间的推移,您正在创建越来越多的计时器,而不是创建一次性使用的计时器。 You will need to call clearInterval(timer_id_goes_here) to clear the timer.您需要调用clearInterval(timer_id_goes_here)来清除计时器。 See code examples in the link below.请参阅下面链接中的代码示例。

https://www.w3schools.com/jsref/met_win_setinterval.asp https://www.w3schools.com/jsref/met_win_setinterval.asp

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

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