Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React-useState-为什么setTimeout函数没有最新状态值?_Javascript_Reactjs_React Hooks - Fatal编程技术网

Javascript React-useState-为什么setTimeout函数没有最新状态值?

Javascript React-useState-为什么setTimeout函数没有最新状态值?,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,最近我在做React钩子,遇到了一个问题/疑问 下面是重现该问题的基本实现,在这里我只需点击按钮切换标志(状态)变量 const [flag, toggleFlag] = useState(false); const data = useRef(null); data.current = flag; const _onClick = () => { toggleFlag(!flag); // toggleFlag(!data.current); // wo

最近我在做React钩子,遇到了一个问题/疑问

下面是重现该问题的基本实现,在这里我只需点击按钮切换
标志
(状态)变量

  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>
  );
const[flag,toggleFlag]=useState(false);
const data=useRef(空);
data.current=标志;
const_onClick=()=>{
toggleFlag(!flag);
//toggleFlag(!data.current);//正在工作
设置超时(()=>{
toggleFlag(!flag);//没有最新值,为什么?
//toggleFlag(!data.current);//正在工作
}, 2000);
};
返回(
{标志?“真”:“假”}
);
我想出了一些其他的方法来解决这个问题,比如使用useRef或useReducer,但是这是正确的还是只有useState才能解决这个问题

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


沙盒URL-

这可以归结为闭包在JavaScript中的工作方式。赋予
setTimeout
的函数将从初始渲染中获取
标志
变量,因为
标志
没有变化

您可以将函数作为参数指定给
toggleFlag
。此函数将获得正确的
标志
值作为参数,此函数返回的内容将替换状态

示例

const{useState}=React;
函数App(){
const[flag,toggleFlag]=useState(false);
const_onClick=()=>{
toggleFlag(!flag);
设置超时(()=>{
toggleFlag(flag=>!flag)
}, 2000);
};
返回(
{标志?“真”:“假”}
);
}
render(,document.getElementById(“根”))

赋予
setTimeout
的函数将从
\onClick
函数中获取
标志
变量。每次渲染时都会创建
\onClick
函数,并“存储”
标志
变量在此渲染上获得的值

function App() {
  const [flag, toggleFlag] = useState(false);
  console.log("App thinks that flag is", flag);

  const _onClick = () => {
    console.log("_onClick thinks that flag is", flag);
    toggleFlag(!flag);

    setTimeout(() => {
      console.log("setTimeout thinks that flag is", flag);
    }, 100);
  };

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

\u onClick
是否在每次渲染时都会得到一个新的闭包和一个新的
标志
值?@UjinT34是的,但是当第一次调用
\u onClick
时,会创建超时,然后在稍后调用超时函数时,会在初始渲染的上下文中查找
标志
,因此它会得到“旧的”关闭fot
setTimeout
何时创建?我认为它是在每次调用
\u onClick
并获取
\u onClick
捕获的
标志时创建的,而不是原始的
标志
变量。@UjinT34如果将
App
视为一个函数,我认为这是有意义的,每次重新渲染都会导致对
App
函数的新调用。对
App
的第一次调用在对
App
的第二次调用中没有“看到”变量。可能是我的“初始渲染”错误。对我来说,这听起来像是
setTimeout
永远有
flag=false
,就像第一次调用
App
一样。请核对我的答案。
App thinks that flag is false

_onClick thinks that flag is false
App thinks that flag is true
setTimeout thinks that flag is false

_onClick thinks that flag is true
App thinks that flag is false
setTimeout thinks that flag is true