React - useState - 为什么 setTimeout 函数没有最新的状态值? [英] React - useState - why setTimeout function does not have latest state value?

查看:30
本文介绍了React - useState - 为什么 setTimeout 函数没有最新的状态值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我在研究 React Hooks,但遇到了一个问题/疑问?

下面是重现问题的基本实现,这里我只是在单击按钮时切换 flag(状态)变量.

 const [flag, toggleFlag] = useState(false);const 数据 = useRef(null);data.current = 标志;const _onClick = () =>{toggleFlag(!flag);//toggleFlag(!data.current);//在职的setTimeout(() => {toggleFlag(!flag);//没有最新值,为什么?//toggleFlag(!data.current);//在职的}, 2000);};返回 (<div className="应用程序"><button onClick={_onClick}>{flag ?"true" : "false"}</button>

);

我想出了一些其他方法来解决这个问题,比如使用 useRef 或 useReducer,但这是正确的还是有其他方法可以仅使用 useState 来解决这个问题?

此外,如果有人解释为什么我们在 setTimeout 中获得旧的状态值,那将非常有帮助.

沙盒网址 - https://codesandbox.io/s/xp540ynomo

解决方案

这归结为闭包在 JavaScript 中的工作原理.赋予 setTimeout 的函数将从初始渲染中获取 flag 变量,因为 flag 未发生变异.

您可以改为提供一个函数作为 toggleFlag 的参数.此函数将获取正确的 flag 值作为参数,此函数返回的内容将替换状态.

示例

const { useState } = React;功能应用(){const [标志,toggleFlag] = useState(false);const _onClick = () =>{toggleFlag(!flag);setTimeout(() => {toggleFlag(flag => !flag)}, 2000);};返回 (<div className="应用程序"><button onClick={_onClick}>{flag ?"true" : "false"}</button>

);}ReactDOM.render(, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"><;/脚本><script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script><div id="root"></div>

Recently I was working on React Hooks and got stuck with one problem/doubt?

Below is a basic implementation to reproduce the issue, Here I'm just toggling flag (a state) variable on click of the button.

  const [flag, toggleFlag] = useState(false);
  const data = useRef(null);
  data.current = flag;

  const _onClick = () => {
    toggleFlag(!flag);
    // toggleFlag(!data.current); // working

    setTimeout(() => {
      toggleFlag(!flag); // does not have latest value, why ?
      // toggleFlag(!data.current); // working
    }, 2000);
  };

  return (
    <div className="App">
      <button onClick={_onClick}>{flag ? "true" : "false"}</button>
    </div>
  );

I figured out some other way to overcome this problem like using useRef or useReducer, but is this correct or is there any other way to solve this with useState only?

Also, it would be really helpful if anyone explains why we get old value of state inside the setTimeout.

Sandbox URL - https://codesandbox.io/s/xp540ynomo

解决方案

This boils down to how closures work in JavaScript. The function given to setTimeout will get the flag variable from the initial render, since flag is not mutated.

You could instead give a function as argument to toggleFlag. This function will get the correct flag value as argument, and what is returned from this function is what will replace the state.

Example

const { useState } = React;

function App() {
  const [flag, toggleFlag] = useState(false);

  const _onClick = () => {
    toggleFlag(!flag);

    setTimeout(() => {
      toggleFlag(flag => !flag)
    }, 2000);
  };

  return (
    <div className="App">
      <button onClick={_onClick}>{flag ? "true" : "false"}</button>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

这篇关于React - useState - 为什么 setTimeout 函数没有最新的状态值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆