reactjs - useEffect 依赖项列表及其包含所有使用的变量的最佳实践

标签 reactjs react-hooks use-effect

根据 https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect 的 React 文档当使用 useEffect 依赖数组时,您应该传入效果中使用的所有值。

If you use this optimization, make sure the array includes all values from the component scope (such as props and state) that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders. Learn more about how to deal with functions and what to do when the array values change too often.

我不知道这个钩子(Hook)在幕后是如何工作的,所以我在这里猜测。 由于闭包内的变量可能会过时,这意味着该函数已缓存在某处。但是为什么要缓存该函数,因为除非依赖项发生更改并且无论如何都需要重新创建该函数,否则该函数不会被调用?

我制作了一个小型测试组件。

function App() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);

  useEffect(() => {
    console.log("b", b);
  }, [a]);

  return (
    <div>
      <div>App {a}</div>
      <button
        onClick={() => {
          setA(a + 1);
        }}
      >
        AddA
      </button>
      <button
        onClick={() => {
          setB(b + 1);
        }}
      >
        AddB
      </button>
    </div>
  );
}

您可以在这里尝试一下:https://codesandbox.io/s/react-hooks-playground-forked-m5se8而且它运行得很好,没有陈旧的值。有人可以解释一下我缺少什么吗?

编辑: 反馈我的问题不完全清楚后,添加一个更具体的问题:

当页面加载后,我单击 AddB 按钮,然后单击 AddA 按钮时,控制台中显示的值为 1。根据文档,我应该得到一个过时的值 (0)。为什么情况并非如此?

最佳答案

When after a page load I click on AddB button and then click on AddA button, value displayed in console is 1. According to the docs, I should get a stale value (0). Why is this not the case?

在这种情况下,您看不到过时值的原因是,当您单击 AddA 时,会发生重新渲染。在新的渲染中,由于 a 的值与之前的渲染不同,因此 useEffect 将计划在 React 更新 UI 后运行(但是它将引用的值将是 < em>来自当前渲染 - 因为传递给 useEffect 的函数每次其依赖项之一发生更改时都会重新创建,因此它会从该渲染中捕获值)。

由于上述原因,这就是为什么您会看到 b 的新值。

但是如果你有这样的代码

React.useEffect(() => {
    const timer = window.setInterval(() => {
       setB(b + 1);
    }, 1000);
    return () => {
      window.clearInterval(timer);
    };
  }, []);

b 将是一个过时的闭包。由于 useEffect 没有重新运行,b 始终具有创建它的渲染器中的值,即第一个渲染器,上面的代码将无法按预期工作,您可以自己检查。


我将添加上面 Patrick Roberts 的评论,因为它很好地解释了恕我直言,当 React 文档说“否则,您的代码将引用以前渲染中的陈旧值”时可能意味着什么:

the problem is that you had to click on AddA button in the first place. Between the time you click AddB and AddA, the effect references b from a stale closure

关于reactjs - useEffect 依赖项列表及其包含所有使用的变量的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67676829/

相关文章:

javascript - 在useEffect中调用函数后在antd库的输入字段内设置默认值

javascript - React Hooks 中用于传递参数的单击事件的语法是什么

javascript - 如何在 React 中将函数链接在一起

css - 如何在剪贴板中复制颜色,reactjs

javascript - onClick 函数需要两次单击才能更新状态

reactjs - 为什么当底层组件重新渲染时,popper 会跳转到左上角?

javascript - 使用 date-fns 根据用户区域设置格式化日期

javascript - 如何使用 webpack 将全局 JS 文件包含到我的 React 项目中?

javascript - 在保留类类型的同时为嵌套对象 react setState

javascript - React Hooks - 0 vs. 空数组作为 useEffect 中的第二个参数