代码之家  ›  专栏  ›  技术社区  ›  Alana Storm

反应:为什么将变量列为依赖项“解决”了过时的闭包问题?

  •  0
  • Alana Storm  · 技术社区  · 4 年前

    我在试着理解我所看到的关于 React and stale closures .

    具体来说,据我所知,术语“过时闭包”用于描述一个场景,其中 useEffect 函数是这样构造的

    function WatchCount() {
      const [count, setCount] = useState(0);
    
      useEffect(function() {
        setInterval(function log() {
          console.log(`Count is: ${count}`);
        }, 2000);
      }, []);
    
      return (
        <div>
          {count}
          <button onClick={() => setCount(count + 1) }>
            Increase
          </button>
        </div>
      );
    }
    

    反应呼叫 WatchCount count 变量。当javascript调用 log 功能两秒钟后 变量将绑定到 计数 是第一个打电话来的。价值 计数 不会反映在的渲染上可能发生的更新 这发生在第一次渲染和最终触发间隔代码之间。

    “解决”这个问题的一般建议是在dependencies数组中列出您的变量——这个数组的第二个参数 使用效果

    useEffect(function iWillBeStale() {
      setInterval(function log() {
        console.log(`Count is: ${count}`);
      }, 2000);
    }, [count]);
    

    作为一个javascript程序员,我不明白这是如何“解决”问题的。我们在这里所做的就是创建一个包含变量的数组,并将该数组传递给 使用效果 我天真的看法是 计数 日志 手表计数

    我是否遗漏了javascript范围的一些细微差别?

    使用效果 你在处理这些变量吗?

    或者第三件事?

    0 回复  |  直到 4 年前
        1
  •  1
  •   Bergi    4 年前

    我是否遗漏了javascript范围的一些细微差别?

    useEffect 不影响闭包,closed over常量保持其值。

    使用效果 使用效果

    同样,th effect函数返回一个cleanup函数,该函数在组件卸载时或下次运行effect之前运行(当依赖项更改时)。此清除函数调用 clearInterval ,这意味着不再执行过时的闭包,并且并发活动间隔的数量不会增加。

    count

    const [count, setCount] = useState(0);
    const countRef = useRef(0);
    countRef.current = count;
    
    useEffect(function() {
      setInterval(function log() {
        console.log(`Count is: ${countRef.current}`);
      }, 2000);
    }, []);