javascript - 在 setInterval 中使用 React 状态 Hook 时状态不更新

标签 javascript reactjs react-hooks

我正在试用新的 React Hooks并有一个带有计数器的时钟组件,该计数器应该每秒增加一次。但是,该值不会增加超过 1。

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/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

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

最佳答案

原因是因为传递给 setInterval 闭包的回调只访问了第一次渲染中的 time 变量,它没有访问新的 time 值在后续渲染中,因为 useEffect() 没有被第二次调用。

timesetInterval 回调中的值始终为 0。

和你熟悉的setState一样,state hooks有两种形式:一种是获取更新后的状态,另一种是传入当前状态的回调形式。你应该使用第二种在 setState 回调中形成并读取最新的状态值,以确保您在递增之前拥有最新的状态值。

Bonus: Alternative Approaches

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/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

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

关于javascript - 在 setInterval 中使用 React 状态 Hook 时状态不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53024496/

相关文章:

javascript - React 列表索引不正确

reactjs - 样式组件按钮中的两种颜色

javascript - 在沙箱中的服务器上运行 JavaScript 代码

javascript - 修改框架元素的CSS

javascript - React+Redux - Uncaught Error : Expected the reducer to be a function

javascript - React.js 中性能最高但功能最全的样式方法是什么

reactjs - 使用 Webpack 在 Electron 项目中使用外部目录中的组件

javascript - useEffect 的奇怪行为

javascript - 处理搜索结果和 Bootstrap 模式

javascript - Clipper.js 不适用于坐标集