【问题标题】:ReactJS useEffect dependency warning leads to infninite loopReactJS useEffect 依赖警告导致无限循环
【发布时间】:2021-01-08 07:22:46
【问题描述】:

在我的功能组件中,我有状态,每当它发生变化时,我都想做一些事情。所以我使用了useEffect,但它给出了“依赖缺失”错误。在我将错误中显示的所有依赖项放入之后,我得到了无限循环。代码如下:

const [keywords, setKeywords] = useState<Keyword[]>();
const [currentPage, pagingConfig, setPagingConfig] = usePaging();

  useEffect(() => {
    const loadKeywords = async () => {
      const { current, pageSize } = pagingConfig;
      const keywords = await getKeywords(current as number, pageSize as number);
      setKeywords(keywords.data.data);
      setPagingConfig({
        ...pagingConfig,
        total: keywords.data.total,
      });
    };
    loadKeywords();
  }, [currentPage]); // Requires to add pagingConfig and setPagingConfig

如果添加了所需的依赖项,我将获得无限循环。

我怎样才能避免这个错误?

【问题讨论】:

  • 是错误还是 ESlint 警告?
  • 发生这种情况是因为setPagingConfig 更新了useEffect 中的状态,然后useEffect 重新运行,因为pagingConfig 发生了变化,然后setPagingConfig 更新了useEffect 中的状态...你明白了。如果 pagingConfig 实际上有不同的keywords.data.total,您应该只更新它
  • 这是一个 ESLint 警告
  • 需要谨慎对待该特定警告。很多时候,它可以甚至必须被忽略。没有它,您的代码可以正常工作。不是吗?我不确定是什么原因,但我认为可能是如果你通过 const 声明一个函数,ESLint 不会立即正确识别它

标签: reactjs react-hooks infinite-loop react-state react-functional-component


【解决方案1】:

这是我的看法。

  • 首先,我在反应编码中也看到了“依赖缺失”这句话。如果我没记错,那就是警告。也许,你可以澄清一下。根据我的经验,你可以忽略它,只要它不影响你的最终输出。您必须记住,内置工具遵循规则和语义,但您需要决定何时可以忽略警告。

  • 其次,一旦你添加了缺失的依赖项(以消除警告),你实际上是在你的 useEffect 中进行状态更改。通过定义,视图被再次渲染,然后你又回到了 useEffect 中。所以,这就是你得到一个无限循环的原因。

解决办法是,

  • 暂时忽略警告。
  • 如果您真的不希望出现警告,请重新设计您的组件或使用 Hooks 以确保每个组件/Hook 只处理项目的一部分。

【讨论】:

    【解决方案2】:

    发生无限循环是因为

    1. setPagingConfig 更新 useEffect 中的状态
    2. useEffect 重新运行,因为 pagingConfig 发生了变化,所以重新渲染会发生更新的依赖项
    3. setPagingConfig 更新 useEffect 中的状态

    你去,你有一个无限循环

    如果pagingConfig 实际上有不同的keywords.data.total,您应该只更新它

    【讨论】:

      【解决方案3】:

      在这种情况下,要走的路是只做状态改变,如果值改变了:

      const [keywords, setKeywords] = useState<Keyword[]>();
      const [currentPage, pagingConfig, setPagingConfig] = usePaging();
      
      useEffect(() => {
        const loadKeywords = async () => {
          const { current, pageSize } = pagingConfig;
          const newKeywords = await getKeywords(current as number, pageSize as number);
          if (newKeywords.data.data !== keywords) {
            setKeywords(newKeywords.data.data);
            setPagingConfig({
              ...pagingConfig,
              total: keywords.data.total,
            });
          }
        };
        loadKeywords();
      }, [currentPage, pagingConfig, setPagingConfig]);
      

      这种方式在第二次迭代状态下不再更新,因为关键字没有变化。

      【讨论】:

        猜你喜欢
        • 2021-09-27
        • 2021-07-25
        • 2020-11-23
        • 2020-08-27
        • 2020-11-16
        相关资源
        最近更新 更多