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

Web*_*tor 4 javascript reactjs use-effect

比较以下两个组件:

儿童.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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

它们本质上是相同的。两者之间的区别在于Child.js从其父获取状态变量count及其 setter setCount,而Child2.js 自己设置该状态变量。

它们都工作正常,但是Child.js(并且只有Child.js)抱怨“缺少依赖项:'setCount'。” 添加setCount到依赖项数组会使警告消失,但我试图弄清楚为什么这是必要的。为什么需要依赖Child但不是Child2

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

Shu*_*tri 8

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

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

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

useEffect(() => {
   setInterval(() => {
      setCount(prevCount => prevCount + 1);
   }, 1000);
   // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) 
Run Code Online (Sandbox Code Playgroud)