React Hook中带有setInterval()的Javascript闭包
在下面的示例中,我希望console中的计数值会像UI中一样增加。但是,它不是,值始终为0,但值在UI中增加。我知道这个问题可能与Javascript关闭有关。在我的理解中,React Hook中带有setInterval()的Javascript闭包,javascript,reactjs,closures,react-hooks,Javascript,Reactjs,Closures,React Hooks,在下面的示例中,我希望console中的计数值会像UI中一样增加。但是,它不是,值始终为0,但值在UI中增加。我知道这个问题可能与Javascript关闭有关。在我的理解中,count应该指的是useState中的值。由于计数由设置计数更新,因此该值不断增加。然而,为什么它在日志中没有增加? 演示: 导出默认函数App(){ const[count,setCount]=useState(0); 函数innerFunction(){ return()=>{ 日志(“计数:”,计数); 设置计数(c
count
应该指的是useState
中的值。由于计数
由设置计数
更新,因此该值不断增加。然而,为什么它在日志中没有增加?
演示:
导出默认函数App(){
const[count,setCount]=useState(0);
函数innerFunction(){
return()=>{
日志(“计数:”,计数);
设置计数(c=>c+1);
};
}
useffect(()=>{
const id=setInterval(innerFunction(),1000);
return()=>clearInterval(id);
}, []);
返回{count};
}
问题在于,在setInterval回调中,count的值没有改变,因为我们创建了一个闭包,将count的值设置为0,就像运行效果回调时一样
在第一次渲染时,closure log()将count变量捕获为0。稍后,即使计数增加,log()仍然从初始渲染开始使用计数作为0。log()是一个过时的闭包
解决方案是让useffect()知道闭包日志()取决于计数,并正确处理间隔的重置:
将计数添加为useEffect中的依赖项
useEffect(() => {
const id = setInterval(innerFunction(), 1000);
return () => clearInterval(id);
}, [count]);
正确设置依赖项后,useffect()会在计数发生变化时立即更新闭包
解释
在没有依赖项的情况下,仅在最初调用useffect()。它不会被重新命名
useEffect(() => {
console.log("is re-rendering");
const id = setInterval(innerFunction(), 1000);
return () => clearInterval(id);
}, []);
此处,“正在重新渲染”“只记录一次
如果使用此语法设置状态,而不是函数语法(获取最新计数状态)。它还将行为显示为log as stale闭包
setCount( count + 1); //always 1 as it gets 0 as count value
由于useffect在count更改后不会调用,因此它们采用相同的初始输入并给出相同的初始输出,因为它们不知道更改
如果我们将count添加为依赖项,则每当count值更改时,就会重新调用useffect,并且setInterval也会使用新的更新输入重新初始化
更多信息
示例
我用一个简单的例子说明了一个类似的问题
这里,我改变了OutVar的值(在第一次调用Outtfn之后,我们认为它是一个<强>计数>强>状态。 但它的最新变化没有得到反映。这就是闭包的工作原理
让outerVar='initial-outer'
函数outerfn(outerVar){
返回函数innerfn(innerVar){
console.log('外部变量:'+outerVar)
console.log('内部变量:'+innerVar)
}
}
设newfn=outerfn(outerVar)
outerVar=“updated outer”//outerVal现在已更改
newfn('inside')//但是初始的outerVal在这里打印
newfn=outerfn(outerVar)//使用更新的值重置闭包(如向useEffect添加依赖项)
newfn('inside')//现在打印更新的outerVal
我不明白closure log()将count变量捕获为0
。你能给我更多的解释吗?我已经更新了我的答案。希望它更清楚:)谢谢你更新的解释。当我们继续调用setCount()
时,为什么不更新计数值?为什么console.log(“count:,count”)代码>未获取更新的计数?计数由setCount()更新。但是提供给setInterval的函数没有重新初始化以知道count的更新值。这是因为使用React Hook时,count
是不可变的吗?更具体地说,console.log(“count:”,count)代码>在第一次渲染中设置,因此计数
为0。即使计数
已更新,新的计数
也不是第一次渲染中的计数
。我的理解正确吗?
setCount( count + 1); //always 1 as it gets 0 as count value