Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/23.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:在传递给类构造函数的回调函数中使用state不会使用state的最新版本_Javascript_Reactjs_React State_React State Management - Fatal编程技术网

Javascript React:在传递给类构造函数的回调函数中使用state不会使用state的最新版本

Javascript React:在传递给类构造函数的回调函数中使用state不会使用state的最新版本,javascript,reactjs,react-state,react-state-management,Javascript,Reactjs,React State,React State Management,很抱歉,标题令人困惑,但下面是发生的情况: 在MyComponent中,我正在使用useStateReact钩子设置count状态。 一旦组件挂载(即没有依赖项的useffect),我将实例化两个MyClass对象,其中第一个参数作为一个回调函数来递增状态,第二个参数是调用回调函数的超时时间 MyClass的第一个实例在1000毫秒内调用回调,并为count设置新值,该值一旦更新,将记录在第二个useffect中 但是,当MyClass的第二个实例调用回调(在timeOut3000毫秒之后),并

很抱歉,标题令人困惑,但下面是发生的情况:

MyComponent
中,我正在使用
useState
React钩子设置
count
状态。 一旦组件挂载(即没有依赖项的
useffect
),我将实例化两个
MyClass
对象,其中第一个参数作为一个回调函数来递增状态,第二个参数是调用回调函数的
超时时间

MyClass
的第一个实例在1000毫秒内调用回调,并为
count
设置新值,该值一旦更新,将记录在第二个
useffect

但是,当
MyClass
的第二个实例调用回调(在
timeOut
3000毫秒之后),并尝试增加
count
值时,它使用了
MyClass
实例化时的
count
状态(该状态为0),因此它将
count
增加到1(想要的行为是增加到2,因为
MyClass
的第一个实例已经从0增加到1)

这与
setState
的异步行为无关,因为很明显,对
count
的第一次更新发生在第二个实例再次尝试更新之前(第二个
useffect
在更新
count
状态时被调用,您可以从控制台日志消息中看到,在第二个
MyClass
实例调用回调之前,会调用第二个
useffect

jsiddle链接:

总之,我认为问题在于回调函数中的
count
状态是回调函数传递给
MyClass
构造函数时
count
状态的副本

本例的解决方案可能是在更新
count
状态时(在第二个
useffect
中),仅实例化
MyClass
的第二个实例,但这不是我正在寻找的解决方案

另一个解决方案是使用
setCount(prevCount=>prevCount+1)
来增加
count
,但这在我的实际应用程序中是不可行的(
MyComponent
MyClass
是我为这个问题编写的真实React应用程序的一个框架示例)

我希望能够在组件装载时(在first
useEffect
中)实例化类,并使回调引用最新版本的
count

是否有解决方案^或者没有办法绕过此javascript和React实现?感谢阅读所有这些,我知道它很长:)

import React,{useState,useffect}来自“React”;
类MyClass{
构造函数(回调,超时){
//以超时毫秒为单位调用回调
this.timeOutId=setTimeout(()=>{
回调();
},超时)
}
clearTimeOut(){
clearTimeout(this.timeOutId);
}
}
函数MyComponent(){
var[count,setCount]=useState(0);
//组件没有安装
useffect(()=>{
设myClass1=newMyClass(funcToCallback,1000);
设myClass2=新的MyClass(funcToCallback,3000);
//当组件卸载时,清除MyClass实例的超时
return()=>{
myClass1.clearTimeOut();
myClass2.clearTimeOut();
}
}, []);
//计数器状态更新
useffect(()=>{
日志(“计数更新为:”,计数);
},[计数])
//获取计数器并将其递增1
函数funcToCallback(){
log(“调用回调”);
设newCount=count+1;
incCount(newCount);
}
函数incCount(newCount){
log(“新计数:”,新计数);
setCount(newCount);
}
返回(
计数:{COUNT}
)
}

count
为0时,使用的
funcToCallback
是组件初始装载中的一个。使用
const
声明的变量不会更改,并且
useffect
回调只调用一次,
funcToCallback
关闭的
count
永远保持为0

最简单的修复方法是改用setter的函数版本,它会将先前的状态作为参数提供给您,然后您可以增加它

  function incCount(newCount){
    console.log("NEW COUNT: ", newCount);
    setCount(newCount);
  }


非常好的第一个问题!你好,Jonas,谢谢分享!是的,我知道闭包问题,我提供了与你在我文章结尾时相同的答案,但是我正在寻找另一个解决方案,因为useState的函数版本在我的实际应用中不是一个可行的解决方案。(我写这段代码是作为关闭问题的一个例子,我的应用程序处理关闭问题,但在不同的上下文中)。
  function incCount(newCount){
    console.log("NEW COUNT: ", newCount);
    setCount(newCount);
  }
  function incCount(){
    setCount((lastCount) => {
      console.log("NEW COUNT: ", (lastCount + 1));
      return lastCount + 1;
    });
  }