在setInterval中使用React状态挂钩时状态

在setInterval中使用React状态挂钩时状态

本文介绍了在setInterval中使用React状态挂钩时状态未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试新的反应钩子,并且有一个带有计数器应该每秒增加.但是,该值不会增加到超过一.

I'm trying out the new React Hooks and have a Clock component with a counter which is supposed to increase every second. However, the value does not increase beyond one.

function Clock() {
  const [time, setTime] = React.useState(0);
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      setTime(time + 1);
    }, 1000);
    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return (
    <div>Seconds: {time}</div>
  );
}

ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

<div id="app"></div>

推荐答案

原因是因为传递给setInterval的闭包的回调仅访问第一个渲染器中的time变量,它无权访问新的time值在后续渲染中显示,因为useEffect()不会第二次调用.

The reason is because the callback passed into setInterval's closure only accesses the time variable in the first render, it doesn't have access to the new time value in the subsequent render because the useEffect() is not invoked the second time.

timesetInterval回调中始终为0.

就像您熟悉的setState一样,状态挂钩有两种形式:一种是采用更新状态的形式,另一种是将当前状态传入的回调形式.您应该使用第二种形式并阅读最新的形式setState回调中的状态值,以确保在递增之前具有最新的状态值.

Like the setState you are familiar with, state hooks have two forms: one where it takes in the updated state, and the callback form which the current state is passed in. You should use the second form and read the latest state value within the setState callback to ensure that you have the latest state value before incrementing it.

Dan Abramov在他的博客帖子,并提供了解决此问题的其他方法.强烈建议阅读!

Dan Abramov, goes in-depth into the topic about using setInterval with hooks in his blog post and provides alternative ways around this issue. Highly recommend reading it!

function Clock() {
  const [time, setTime] = React.useState(0);
  React.useEffect(() => {
    const timer = window.setInterval(() => {
      setTime(prevTime => prevTime + 1); // <-- Change this line!
    }, 1000);
    return () => {
      window.clearInterval(timer);
    };
  }, []);

  return (
    <div>Seconds: {time}</div>
  );
}

ReactDOM.render(<Clock />, document.querySelector('#app'));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

<div id="app"></div>

这篇关于在setInterval中使用React状态挂钩时状态未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 11:03