• React报错之Rendered more hooks than during the previous render


    正文从这开始~

    总览

    当我们有条件地调用一个钩子或在所有钩子运行之前提前返回时,会产生"Rendered more hooks than during the previous render"错误。为了解决该错误,将所有的钩子移到函数组件的顶层,以及不要在条件中使用钩子。

    rendered-more-hooks-than-during-previous-render.png

    这里有个示例用来展示错误是如何发生的。

    // App.js
    
    import {useEffect, useState} from 'react';
    
    export default function App() {
      const [counter, setCounter] = useState(0);
    
      // ⛔️ Error: Rendered more hooks than during the previous render.
      if (counter > 0) {
        // 👇️ calling React hook conditionally
        useEffect(() => {
          console.log('hello world');
        });
      }
    
      return (
        <div>
          <button onClick={() => setCounter(counter + 1)}>toggle loadingbutton>
          <h1>Hello worldh1>
        div>
      );
    }
    

    代码的问题在于,我们有条件地调用了useEffect钩子。

    顶层调用

    为了解决该错误,我们必须将条件移到钩子内部。因为React钩子只能在顶层调用。

    import {useEffect, useState} from 'react';
    
    export default function App() {
      const [counter, setCounter] = useState(0);
    
      // ✅ hook is called at top level (not conditionally)
      useEffect(() => {
        if (counter > 0) {
          console.log('hello world');
        }
      });
    
      return (
        <div>
          <button onClick={() => setCounter(counter + 1)}>toggle loadingbutton>
          <h1>Hello worldh1>
        div>
      );
    }
    

    我们将if语句移动到了useEffect钩子内部。

    这就解决了错误,因为我们必须确保每次组件渲染时,React钩子都以相同的顺序被调用。

    这意味着我们不允许在循环、条件或嵌套函数中使用钩子。

    这里有另外一个示例用来展示错误是如何发生的。

    import {useState} from 'react';
    
    export default function App() {
      const [counter, setCounter] = useState(0);
    
      // 👇️ this returns before second hook runs if condition is met
      if (counter > 0) {
        return <h2>Returning earlyh2>;
      }
    
      // ⛔️ Error because hook is called conditionally
      const [color, setColor] = useState('salmon');
    
      return (
        <div>
          <button onClick={() => setCounter(counter + 1)}>toggle loadingbutton>
          <h1>Hello worldh1>
        div>
      );
    }
    

    问题在于,第二个useState钩子只有在上面的条件没有满足时才会被调用。

    条件之上

    为了解决这个错误,把所有的钩子移到组件的顶层,在任何可能返回值的条件之上。

    import {useState} from 'react';
    
    export default function App() {
      const [counter, setCounter] = useState(0);
    
      const [color, setColor] = useState('salmon');
    
      // 👇️ condition that may return early must be below all hooks
      if (counter > 0) {
        return <h2>Returning earlyh2>;
      }
    
      return (
        <div>
          <button onClick={() => setCounter(counter + 1)}>toggle loadingbutton>
          <h1>Hello worldh1>
        div>
      );
    }
    

    我们把第二个useState钩子移动到有可能返回一个值的if条件上面。

    这是很有帮助的,因为钩子现在在顶层,并且有可预测的行为,允许React在调用useStateuseEffect之间正确地保存状态。

    就像文档中所说的那样:

    • 只从React函数组件或自定义钩子中调用Hook
    • 只在最顶层使用 Hook
    • 不要在循环,条件或嵌套函数中调用 Hook
    • 确保总是在你的 React 函数的最顶层以及任何 return 之前使用 Hook

    这有助于React在多个useStateuseEffect调用之间保留钩子的状态。

  • 相关阅读:
    io+day5
    QProcess 调用 ffmpeg来处理音频
    如何将jpg转化为png?
    ssh-keygen命令生成RSA、ed25519类型密钥对
    CDN是啥?
    pandas教程:Apply:General split-apply-combine 通常的分割-应用-合并
    ABAP接口部分-Web Service提供者与消费者
    C语言入门--指针
    上海亚商投顾:沪指探底回升跌0.75% 旅游板块集体大涨
    华为od 面试题及流程 (前后端)
  • 原文地址:https://www.cnblogs.com/chuckQu/p/16644590.html