[英]useEffect infinite loop when updating state and including dependency array
[英]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 的useState
和useReducer
要求与详尽的 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.