React Hook中带有setInterval()的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

在下面的示例中,我希望console中的计数值会像UI中一样增加。但是,它不是,值始终为0,但值在UI中增加。我知道这个问题可能与Javascript关闭有关。在我的理解中,
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
由于useffectcount更改后不会调用,因此它们采用相同的初始输入并给出相同的初始输出,因为它们不知道更改

如果我们将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