为什么在通过 props 传入时,状态变量的 setter 需要作为 useEffect 的依赖项?

Why is a state variable's setter needed as a dependency with useEffect when passed in through props?

比较以下两个组件:

Child.js

import React, { useEffect } from "react";

function Child({ count, setCount }) { // Note: Has parameter
  useEffect(() => {
    setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);
  }, []);

  return <div>{count}</div>;
}

export default Child;

Child2.js

import React, { useEffect, useState } from "react";

function Child2() { // Note: No parameter
  const [count, setCount] = useState(0); // State variable assigned in component

  useEffect(() => {
    setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);
  }, []);

  return <div>{count}</div>;
}

export default Child2;

它们本质上是一样的。两者的区别在于Child.js获取的是状态变量count及其从父级传入的settersetCount,而Child2.js 设置状态变量本身。

它们都工作正常,但是 Child.js(而且只有 Child.js)抱怨 "a missing dependency: 'setCount'." 将 setCount 添加到 dependencies 数组会使警告消失,但我试图弄清楚为什么这是必要的。为什么 Child 中需要依赖关系而不是 Child2

我在 https://codesandbox.io/s/react-use-effect-dependencies-z8ukl 有工作示例。

ESLint 规则并不是非常智能,无法确定什么可以更改或不能更改,因此会提示您传递在 useEffect 函数回调中使用的每个变量,这样您就不会意外错过这些更改。

由于hooks严重依赖闭包,而初学者程序员很难调试与闭包相关的问题,这里的eslint warning可以很好地帮助避免这种情况。

现在,由于状态更新程序直接从 useState 返回,并且在组件生命周期过程中不会更改,因此您可以避免将其作为依赖项传递并禁用

之类的警告
useEffect(() => {
   setInterval(() => {
      setCount(prevCount => prevCount + 1);
   }, 1000);
   // eslint-disable-next-line react-hooks/exhaustive-deps
}, [])