此代码来自 react 文档:
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setCount(count + 1); // This effect depends on the `count` state
}, 1000);
return () => clearInterval(id);
}, []); // 🔴 Bug: `count` is not specified as a dependency
return <h1>{count}</h1>;
}
他们说:The empty set of dependencies, [], means that the effect will only run once when the component mounts, and not on every re-render. The problem is that inside the setInterval callback, the value of count does not change, because we’ve created a closure with the value of count set to 0 as it was when the effect callback ran. Every second, this callback then calls setCount(0 + 1), so the count never goes above 1.
但是setInterval中的函数不是闭包,所以它的count变量引用Counter的count状态,当setCount运行时Count会改变,所以setInterval中的函数必须能够获得新的count值?我错过了什么吗?
最佳答案
But isn't the function in setInterval is closure so its count variable reference to count state of Counter, when setCount run Count will change and so function in setInterval must be able to get new value of count?
并不真地。闭包关闭单个变量或变量环境。使用 React,当一个组件重新渲染时,整个函数再次运行,为内部的每个变量创建新的绑定(bind)。
比如第一次
Counter
运行,它确实:const [count, setCount] = useState(0);
创建这两个变量。由于useEffect
有一个空的依赖数组,它的回调只会在挂载时运行一次,所以这两个变量是它的闭包将引用的。但是一旦状态发生变化,并且组件重新渲染,函数就会再次运行这一行:
const [count, setCount] = useState(0);
在新范围内再次创建这两个新变量。这个新的count
将增加,但间隔回调不会关闭它。这是一个演示 vanilla JS 中的问题的实时片段:
let i = 0;
const getRenderValue = () => i++;
const Component = () => {
const thisRenderValue = getRenderValue();
console.log('Rendering with thisRenderValue of', thisRenderValue);
if (thisRenderValue === 0) {
setInterval(() => {
console.log('Interval callback sees:', thisRenderValue);
// Run component again:
Component();
}, 1000);
}
};
Component();
关于javascript - 使用 useState Hook 引用函数状态时关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64886247/