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

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

问题描述

最近我正在研究React Hooks,并陷入一个问题/疑问?

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

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

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>
  );

我想出了其他方法来克服此问题,例如使用useRef或useReducer,但这是正确的吗?或者是否有其他方法只能通过useState解决此问题?

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?

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

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

推荐答案

这归结为闭包在JavaScript中的工作方式.由于未更改flag,赋予setTimeout的函数将从初始渲染中获取flag变量.

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.

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

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.

示例

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天全站免登陆