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

Posted

技术标签:

【中文标题】错误:渲染的钩子比上一次渲染时更多【英文标题】:Error: Rendered more hooks than during the previous render 【发布时间】:2021-12-01 00:01:48 【问题描述】:

我有一个组件在页面加载时呈现,然后进行一些调用以获取数据客户端。在初始加载时,一切都按预期工作。但是,当我单击查看更多按钮进行新调用时,控制台中会出现一个错误,提示“渲染的钩子比上一次渲染时更多”。有人对这里可以编辑的内容有任何意见吗?因为此时我有点迷茫

Error: Rendered more hooks than during the previous render.
    at updateWorkInProgressHook (react-dom.development.js:15115)
    at updateMemo (react-dom.development.js:15583)
    at Object.useMemo (react-dom.development.js:16055)
    at useMemo (react.development.js:1607)
    at SecondCall (SecondCall.js:30)
    at renderWithHooks (react-dom.development.js:14938)
    at updateFunctionComponent (react-dom.development.js:17169)
    at beginWork (react-dom.development.js:18745)
    at htmlUnknownElement.callCallback (react-dom.development.js:182)
const SomeItems = (guid) => 
  const 
    data: dataR,
    loading: loadingR,
    error: errorR
   = useQuery(
    'foo',
    
      variables:  guid 
    
  );

  const list = dataR?.foo?.relatedProducts || [];
  const urls = list.map((prod) => prod.url);
  const properties = urls.map((url) => url.substr(url.lastIndexOf('/') + 1));
  const firstvalues = properties.slice(0, 3) || [];

  const [flag, setFlag] = useState(false);
  return (
    <div>
      <h4>Shop this Project</h4>
      <div id="values">
        
          flag
          ? <SecondCall properties=[properties] />
          : <FirstCall properties=[firstvalues] />
        
        <div>
          <button
            id="products"
            type="button"
            onClick=() => setFlag(true)
          >
            See More
          </button>
        </div>
      </div>
    </div>
  );

export const SecondCall = ( properties ) => 
  const valueArray = Object.values(properties);
  const [[destructedValues]] = valueArray;
  const 
    data,
    loading,
    error,
   = useQuery(
    'foo2',
    
      variables: value: destructedValues
    
  );

  if (!data || loading || error) 
    return null;
  

  const list = data?.foo2?.prods || [];
  const items = list.map((prods) => prods.id);
  const 
    data: dataFLS,
    loading: loadingFLS,
    error: errorFLS,
   = useQuery(
    'foo3',
    
      variables: items
    
  );

  if (!dataFLS || loadingFLS || errorFLS) 
    return null;
  

  const data = dataFLS?.foo3?.prods || [];
  return data.map((products, index) => (
    <div key=`prods-$index`>
      <Row key=`related-products-$index`>
        "some divs get rendered with data" 
      </Row>
    </div>
  );
;
export const firstCall = ( firstvalues ) => 
  const valueArray = Object.values(firstvalues);
  const [[destructedValues]] = valueArray;
  const 
    data,
    loading,
    error,
   = useQuery(
    'foo2',
    
      variables:  value: destructedValues
    
  );

  if (!data || loading || error) 
    return null;
  

  const list = data?.foo2?.prods || [];
  const items = list.map((prods) => prods.id);
  const 
    data: dataFLS,
    loading: loadingFLS,
    error: errorFLS,
   = useQuery(
    'foo3',
    
      variables: items
    
  );

  if (!dataFLS || loadingFLS || errorFLS) 
    return null;
  

  const data = dataFLS?.foo3?.prods || [];
  return data.map((products, index) => 
    return (
      <div key=`prods-$index`>
        <Row key=`related-products-$index`>
          "some divs get rendered with data" 
        </Row>
      </div>
    );
  );
;

【问题讨论】:

你在使用 react-query 吗?如果是这样,请将其添加为标签。 graphql 查询 我(有点)为您清理了格式。有时你在大括号和括号等分隔符周围使用额外的空格,有时你不使用,你使用空格来表示块是完全关闭的,有时你使用分号,而在其他地方你没有。 这种霰弹枪格式使得 非常容易 琐碎 错误可以逃避您的注意。 就像将 firstCall 拼写为 'firsCall' 一样,我也修复了它为你。以后请在发布问题之前纠正这些问题。谢谢。 在这种情况下,您的问题是,如果它触发了对useQuery 的第二次调用,则提前返回if (!data || loading || error) return null; 永远不会发生,这违反了钩子规则。 谢谢。对于格式错误,我深表歉意。但这有很大帮助 【参考方案1】:

在您的 SecondCall 组件中,您在 if 语句中返回 null。但由于 useQuery 是一个钩子,所有 useQuery 语句都需要在返回任何内容之前运行。

const data, loading, error = useQuery('foo2', 
  variables: value: destructedValues
)

const list = data?.foo2?.prods || [];
const items = list.map((prods) => prods.id);

const data: dataFLS, loading: loadingFLS, error: errorFLS = useQuery('foo3', 
  variables: items
);

if (!data || loading || error || !dataFLS || loadingFLS || errorFLS) 
    return null;

编辑:显然您在 FirsCall 中也使用了两个 useQuery 语句。同样的逻辑也适用于那里。

【讨论】:

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

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

未处理的拒绝(错误):渲染的钩子比上一次渲染时更多(React Interface GrandStack with ApolloClient)

React/NextJS 使用 UseEffect 错误:渲染的钩子比上一次渲染期间更多

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

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

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