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应用程序的一个框架示例)
我希望能够在组件装载时(在firstuseEffect
中)实例化类,并使回调引用最新版本的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;
});
}