繁体   English   中英

当数组作为依赖项传递时,React 中的 useEffect 在无限循环中运行

[英]useEffect in React runs in an infinite loop, when an array is passed as a dependency

当以下代码在 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任何更改都会导致您的效果运行。 此时您setValue(args)以便args再次更改。 这将导致您的效果再次运行......因此是一个无限循环。

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

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

我发表的这篇文章与您的问题非常相似。 最终结果是您应该使用setState作为函数(即示例中的setState(oldState => oldState) ),此时旧状态不需要是依赖项或useReducer也可以产生相同的效果。

但是,这两种方法都不可能完全符合您可能尝试做的事情,这会产生更多问题,如我稍后发表的这篇文章中所见。 如果他们是纯洁的,那你就没事了。

1 篇文章中的第 4 个解决方案描述了如何积极避免这个问题,但最终我决定使用react-hooks/exhaustive-deps规则并在我有意删除我不想要的依赖项时逐行禁用它。 我不同意这应该是所有这一切之后的规则。

您尝试做的问题是平衡 React 的useStateuseReducer要求与详尽的 deps 要求。 我认为这需要做很多工作来使这些需求比实际生产力更满意。

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

const args = useRef(['a']);
const [value, setValue] = useState(['b']);

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

console.log('value', value);

并且args的值可以在useEffect回调中使用,使用args.current

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM