使用 useEffect 渲染的钩子比上一次渲染时更多

Posted

技术标签:

【中文标题】使用 useEffect 渲染的钩子比上一次渲染时更多【英文标题】:Rendered more hooks than during the previous render using useEffect 【发布时间】:2021-01-06 08:53:50 【问题描述】:

我有一个包含对象数组的组件,其中我基于字符串进行过滤。 问题是当我尝试将此过滤器的返回设置为本地状态时,它会抛出我不太理解原因的错误。

import React,  useState, useEffect  from 'react';
import  useQuery  from '@apollo/react-hooks';
import gql from 'graphql-tag'
const ProductsGrid = () => 


const [productsList, setProductsList] = useState([]);
  const  loading, data  = useQuery(GET_PRODUCTS);
  if (loading) return <div><h4>bla bla bla</h4></div>
  const  merchants  = data;
  let filtered = [];
  merchants.map(merchant => 
    merchant.products.map(product => 
      if (product.name.includes('Polo')) 
        filtered.push(product);
      
    )
  )
  console.log( filtered );

这是打印以下内容:

所以,因为我想要这个数组处于我的状态,所以我决定这样做:setProductsList(filtered); 插入这一行后发生的事情是这样的:

它开始多次渲染。我假设,每次状态更改时,它都会重新渲染组件(如果我错了,请纠正我)。我不知道为什么它会多次这样做。

所以,我想在这里使用 useEffect 来实现预期的行为。

useEffect(() => 
console.log('useeffect', data);
if (data) 
  const  merchants  = data;
  console.log(merchants )
  let filtered = [];
  merchants.map(merchant => 
    merchant.products.map(product => 
      if (product.name.includes('Polo')) 
        filtered.push(product);
        // console.log( filtered );
      
    )
  )
  console.log( filtered );
  setProductsList(filtered);

,[数据])

输出是:

所以,我了解这里发生了什么以及最后一个错误是什么。 我假设我的方法是朝着正确的方向,使用useEffect 只运行一次函数。

【问题讨论】:

显示完整的组件代码。 @adel 这是完整的代码。除了你在这里看到的,只有一个无关紧要的 return abc。 您的问题可能包含完整的代码,但它是零碎的 - 我们不知道 useEffect 如何适合其他所有内容。如果您可以展示完整的组件,或者至少展示足够多的组件,这样我们就可以在原地看到所有钩子的使用情况,这将很有帮助。 @backtick jsfiddle.net/4v2u10yr/1 整个组件脚本在这里。 【参考方案1】:

您的问题是由于useEffect 调用发生在if (loading) 条件之后,该条件提前返回。

在条件返回语句之后调用钩子是非法的,因为它违反了在每次渲染时总是以完全相同的顺序调用钩子的保证。

const  loading, data  = useQuery(GET_PRODUCTS);
const [productsList, setProductsList] = useState([]);
if (loading)
  return (
    <div>
      <h4>bla bla bla</h4>
    </div>
  );  // <-- Cannot use hooks after this point
useEffect(/* ... */)

要解决此问题,请将 useEffect 调用移到条件之前。

【讨论】:

以上是关于使用 useEffect 渲染的钩子比上一次渲染时更多的主要内容,如果未能解决你的问题,请参考以下文章

渲染的钩子比上一次渲染时更多

错误:渲染的钩子比上一次渲染时更多

React Hooks 渲染的钩子比上一次渲染时更多

React - 出现“渲染的钩子比上一次渲染时更多”错误

当钩子的初始值是来自数据库的查询结果时,“比上一次渲染期间渲染的钩子更多”错误

Uncaught Invariant Violation:渲染的钩子比上一次渲染时更多