reactjs - 尽管依赖项没有变化,useEffect 仍运行无限循环

标签 reactjs react-hooks use-effect

我有一个使用钩子(Hook)的函数组件。在 useEffect Hook 中,我只想从后端获取数据并将结果存储在状态中。然而,尽管添加了 data 变量作为依赖项,useEffect 仍然会触发无限循环 - 即使数据没有更改。如何阻止 useEffect 连续触发?

我尝试过空数组 hack,它确实阻止了 useEffect 的连续触发,但这不是所需的行为。例如,如果用户保存新数据,则 useEffect 应该再次触发以获取更新的数据 - 我不想模拟 componentDidMount。

const Invoices = () => {
  const [invoiceData, setInvoiceData] = useState([]);

  useEffect(() => {
    const updateInvoiceData = async () => {
      const results = await api.invoice.findData();
      setInvoiceData(results);
    };
    updateInvoiceData();
  }, [invoiceData]);

  return (
    <Table entries={invoiceData} />
  );
};

我预计 useEffect 在初始渲染后触发,并且仅在发票数据更改时再次触发。

最佳答案

useEffect 依赖项数组的工作方式是检查先前渲染和新渲染的数组中所有项目之间的严格 (===) 等效性。因此,将数组放入 useEffect 依赖项数组中是非常麻烦的,因为与 === 进行数组比较会通过引用检查等效性,而不是通过内容。

const foo = [1, 2, 3];
const bar = foo;
foo === bar; // true

const foo = [1, 2, 3];
const bar = [1, 2, 3];
foo === bar; // false

在效果函数内部,当您执行 setInvoiceData(results) 操作时,您会将 invoiceData 更新为新数组。即使该新数组中的所有项目完全相同,对新 invoiceData 数组的引用也会发生变化,导致效果的依赖关系不同,从而触发再次发挥作用——无限循环。

一个简单的解决方案是从依赖项数组中删除 invoiceData。这样,useEffect 函数的作用基本上与 componentDidMount 类似,它会在组件首次渲染时触发一次且仅触发一次。

useEffect(() => {
    const updateInvoiceData = async () => {
      const results = await api.invoice.findData();
      setInvoiceData(results);
    };
    updateInvoiceData();
  }, []);

这种模式非常常见(并且有用),甚至在 the official React Hooks API documentation 中提到过。 :

If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run. This isn’t handled as a special case — it follows directly from how the dependencies array always works.

关于reactjs - 尽管依赖项没有变化,useEffect 仍运行无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57859484/

相关文章:

javascript - 你应该将 setter 函数传递到 React 钩子(Hook)的依赖数组中吗?

reactjs - React useEffect 包括缺少的依赖项会破坏它

javascript - 如何修复 React Redux 和 React Hook useEffect 缺少依赖项 : 'dispatch'

javascript - 如何将此 Object.values 除以总数?

javascript - 模式打开时触发按钮 onClick

reactjs - 如何在react.js中转换时间戳?

reactjs - 使用 useEffect 与使用 useCallback 处理 API 调用

reactjs - 如何根据 Redux 表单中的另一个输入有条件地显示一个输入?

reactjs - 如何使表单提交将数据保存在 useState Hook 变量中?

javascript - 如果不指定依赖项,useEffect() 有什么意义