javascript - 使用 useState Hook 引用函数状态时关闭

标签 javascript reactjs react-hooks

此代码来自 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/

相关文章:

javascript - React Hook - 只监听窗口 *宽度* 大小的变化

javascript - React 自定义钩子(Hook)重新渲染

UIWebView 中的 Javascript 回调到 C/Objective-C

javascript - 拦截 JavaScript 中的表单提交并阻止正常提交

javascript - 如何删除或隐藏 TinyMCE 图像弹出窗口中的图像描述字段

javascript - 无法通过 props 将事件处理程序发送到子元素

javascript - 错误 : sending a transaction requires a signer while calling aggregate function of Multicall Contract Ethereum

javascript - 使用 input[type=file] 动态加载和渲染 React 组件

javascript - React Hooks 中未使用的 var

javascript - 如何从 pdf.js 中的用户选择中检索文本?