【问题标题】:What should be the dependencies of useEffect Hook?useEffect Hook 的依赖项应该是什么?
【发布时间】:2021-07-04 15:01:50
【问题描述】:

正如所说,useEffect 钩子是我们进行副作用相关部分的地方。我对应该在 useEffect hook 的依赖项数组中传递哪些依赖项感到困惑?

React 文档说

如果您使用此优化,请确保数组包含组件范围内的所有值(例如 props 和 state),这些值会随时间变化并被效果器使用。否则,您的代码将引用以前渲染中的陈旧值。

考虑一个例子:

export default function App() {
  const [count, setCount] = React.useState(0);

React.useEffect(() => {
    console.log("component mounted");
  }, []);


  const update = () => {
    for(let i=0; i<5;i++){
      setCount(count+i)
    }
  };
  return (
    <div>
    {console.log(count)}
      {count}
      <button type="button" onClick={update}>
        Add
      </button>
    </div>
  );
}

按照上面的说法,我们应该将count变量作为依赖传递给useEffect,它会让useEffect重新运行。

但在上面的示例中,不传递 count 依赖项不会对 UI 造成任何问题。没有陈旧的价值。变量按预期更新,UI 使用精确值重新渲染,记录当前值。

所以我的问题是,我们为什么要将 count 变量作为依赖项传递给 useEffect。界面是否正常工作?

更新

我知道每次依赖数组中的值发生变化时都会触发 useEffect 回调。我的问题是什么应该进入依赖数组?我们真的需要传递状态变量吗?

提前致谢。

【问题讨论】:

  • 您没有在 useEffect 中实现任何依赖于 count 变量的逻辑。没有它依赖或没有依赖,它没有任何区别
  • @DebarshiBhattacharjee 如果依赖项为空,即[],那么它只会调用一次 useEffect 的回调,但是如果其中提到了依赖项,那么每次依赖项更改时都会调用回调。
  • 请阅读更新部分

标签: reactjs react-hooks


【解决方案1】:

为了演示和理解问题,打印里面的 count 变量

React.useEffect(() => {
    console.log("component updated ", count);
  }, []); // try to add it here

再次单击该按钮并查看它如何记录到控制台

编辑: 如果您希望 IDE 通知您缺少依赖项,请使用此插件 https://reactjs.org/docs/hooks-rules.html#eslint-plugin

请记住,如果您想模拟 onMount,它仍然会报错

【讨论】:

  • 它是组件安装的。我知道当依赖数组中的值发生变化时会触发 useEffect 回调。我的问题是依赖数组中有什么?我们真的需要传递状态变量吗?
  • 如果您希望仅在挂载时调用您传递的 useEffect 函数,则可以将其保留为空数组。否则,如果您想每次都调用您的函数,那么是的,您应该传递您在函数中使用的所有内容。
  • 是的,我知道。我的意思是我们如何决定什么应该进入依赖数组?
  • 它基于您的需求,您可以想象每次渲染后数组中的所有项目都与上一次渲染中提供的所有项目进行比较。如果数组中的项目之间存在差异(与 === 相比),则执行该函数。
  • 好的明白了。可能这是一个愚蠢的问题。但感谢您的回答。清除了我的疑问。
【解决方案2】:

如果 useEffect 中第二个参数的属性发生变化 - 那么组件将重新渲染。

如果您通过计数 -> 则在计数更改后重新渲染组件 - 一次。

React.useEffect(() => {
    console.log("component mounted");
  }, [count]);

快速回答:

每次需要触发刷新组件时都通过。

【讨论】:

  • 刷新组件是什么意思?
  • 这是反应生命周期组件范围内的术语 - 更新状态 - 不刷新页面 - 在用户交互之后
【解决方案3】:

什么应该进入依赖数组?

那些随时间变化的东西(道具/状态)以及被效果使用的东西。

在示例中,UI 可以正常工作,因为 setState 重新渲染了组件。

但如果我们做一些副作用,比如在count 更改时调用alert,我们必须将count 传递给依赖数组。这将确保在我们的例子中,每次依赖项 (count) 发生变化时都会调用 回调

  React.useEffect(() => {
    alert(`Count ${count}`); // call everytime count changes
  }, [count]); // makes the callback run everytime, the count updates. 

【讨论】:

    【解决方案4】:

    useEffect 将在无限循环中被调用,除非你给它依赖。

    React.useEffect(() => {
        console.log("Looped endlessly");
    }); // dependencies parameter missing
    

    添加一个空的依赖列表会导致它在组件挂载时只被调用一次

    React.useEffect(() => {
        console.log("Called once on component mount");
    }, []); // empty dependency list
    

    将状态添加到依赖列表中,以便在状态更新时调用

    React.useEffect(() => {
        console.log("Called once on component mount and whenever count changes");
        console.log("Count: " + count);
    }, [count]); // count as a dependency
    

    【讨论】:

    • 你不需要在 useEffect 中传递状态。我试图解释 useEffect 是如何工作的,所以你知道如何使用它。您可以将其用作 componentDidMount 的替代品和/或用作状态更改时的侦听器/触发器
    • 感谢您的回答,但我知道 useEffect 是如何工作的。我的问题与依赖数组项有关。
    • 对,我的回答向您展示了实现 useEffect 的 3 种不同方式:无依赖项、空依赖项列表和具有状态的依赖项列表。将计数作为依赖项传递的原因是监视状态并控制在状态更改时如何或是否希望发生任何事情。 useEffect 与你的 UI 无关。
    猜你喜欢
    • 2021-02-23
    • 2021-05-16
    • 2020-10-26
    • 2019-10-24
    • 1970-01-01
    • 2022-06-12
    • 2020-03-07
    • 2020-02-25
    • 2020-06-11
    相关资源
    最近更新 更多