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

时间:2020-03-07 04:21:28

标签: javascript reactjs loops state react-hooks

在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);
}

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

如果我将args的值更改为一个字符串,例如const args = 'a',则没有无限循环。因此,当依赖项是数组时,似乎会出现问题。

2 个答案:

答案 0 :(得分: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上的第四种解决方案描述了如何积极避免此问题,但是最终我决定使用react-hooks/exhaustive-deps规则,并在我故意删除不依赖的依赖项时逐行禁用它想。我不同意这是否应成为规则。

您要解决的问题是React的useStateuseReducer的要求与详尽的dep要求之间的平衡。我认为这导致了很多工作,要使这些要求超出实际生产力。

答案 1 :(得分:0)

使用useRef为我解决了此问题:

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

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

console.log('value', value);

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