【问题标题】:useEffect in React runs in an infinite loop, when an array is passed as a dependency当数组作为依赖项传递时,React 中的 useEffect 在无限循环中运行
【发布时间】:2020-03-07 04:21:28
【问题描述】:

当以下代码在 React 组件中运行时,会导致死循环。为什么将数组作为依赖项传递给useEffect(在本例中为args)会导致这种情况发生?如何阻止无限循环的发生?代码应该只运行一次。

我读到我可以使用 [args.length] 来阻止这种情况的发生,但是 ESLint 规则 react-hooks/exhaustive-deps 会引发错误,所以我想避免这样做。

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

export default function Home() {
  const args = ['a'];
  const [value, setValue] = useState(['b']);

  useEffect(() => {
    setValue(['c']);
  }, [args]);

  console.log('value', value);
}

请注意,在上面的代码中,我什至在 useEffect 回调中根本没有使用或修改 args

如果我将args 的值更改为一个字符串,比如const args = 'a',那么就没有无限循环。所以当依赖是一个数组的时候,问题似乎就出现了。

【问题讨论】:

  • 你能解释一下你想要什么吗?由于 args 不再更改,因此您的代码只能运行一次。让我知道您的目的,以便我可以帮助您。
  • @Shildra 我希望代码只运行一次,但它在无限循环中运行。

标签: javascript reactjs loops state react-hooks


【解决方案1】:

问题是对args 的任何更改都会导致您的效果运行。此时您setValue(args) 所以args 再次更改。这将导致您的效果再次运行......因此是一个无限循环。

如果您将args 设置为与之前相同的字符串,则如果它们根据 react 检测更改的方式匹配,则不会将其注册为更改。这不适用于数组或对象。 {test: 'a'} !== {test: 'a'}['a'] !== ['a']'a' === 'a'1 === 1

我也遇到了你的问题。我最终禁用了react-hooks/exhaustive-deps 规则。但我有更多的数据给你。我努力尝试使用这个规则一段时间。

This post我做的和你的问题很相似。最终结果是您应该使用 setState 作为函数(即您的示例中的 setState(oldState => oldState)),此时旧状态不需要是依赖项或 useReducer 也会产生相同的效果。

然而,这些都不是纯粹的你可能试图做的事情,这会产生更多的问题,如我稍后制作的post 所示。如果它们是纯的,那你很好。

1st post 上的第 4 个解决方案描述了如何积极避免此问题,但最终我决定使用react-hooks/exhaustive-deps 规则并在我故意删除我不想要的依赖项时逐行禁用它。我不同意毕竟这应该成为一个规则。

您要解决的问题是平衡 React 的要求,即 useStateuseReducer 是纯的,以及对详尽的 deps 的要求。我认为这需要做很多工作才能使这些要求高于实际生产力。

【讨论】:

    【解决方案2】:

    使用useRef 为我解决了这个问题:

    const args = useRef(['a']);
    const [value, setValue] = useState(['b']);
    
    useEffect(() => {
      setValue(['c']);
    }, [args]);
    
    console.log('value', value);
    

    并且args 的值可以在useEffect 回调中与args.current 一起使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-09-24
      • 2021-07-25
      • 2020-11-02
      • 2020-01-11
      • 2022-11-10
      • 2021-09-27
      相关资源
      最近更新 更多