Clue Mediator

[Solved] Uncaught Invariant Violation: Rendered more hooks than during the previous render

๐Ÿ“…June 22, 2022
๐Ÿ—ReactJS

When you are working with React Hooks, you may see the error: Uncaught Invariant Violation: Rendered more hooks than during the previous render. In this article, we will show you how to fix this article.

If we conditionally call a hook or return before all of the hooks have finished, we get the error "Rendered more hooks than during the last render". Move all hooks to the top level of the function component and avoid using hooks within conditions to fix the problem.

Checkout more articles on ReactJS

Error

Uncaught Invariant Violation: Rendered more hooks than during the previous render.

Error - Uncaught Invariant Violation: Rendered more hooks than during the previous render - Clue Mediator

Error - Uncaught Invariant Violation: Rendered more hooks than during the previous render - Clue Mediator

Letโ€™s take an example of how the error occurs and how to fix it.

Example 1

import React, {useEffect, useState} from 'react';

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 loading</button>
      <h1>Hello world</h1>
    </div>
  );
}

export default App;

Solution:

Because React hooks can only be invoked at the top level, we must relocate the condition within the hook to fix the issue.

import React, {useEffect, useState} from 'react';

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 loading</button>
      <h1>Hello world</h1>
    </div>
  );
}

export default App;

Example 2

import React, {useState} from 'react';

function App() {
  const [counter, setCounter] = useState(0);

  // this returns before second hook runs if condition is met
  if (counter > 0) {
    return <h2>Returning early</h2>;
  }

  // Error because hook is called conditionally
  const [color, setColor] = useState('salmon');

  return (
    <div>
      <button onclick="{()" ==""> setCounter(counter + 1)}>toggle loading</button>
      <h1>Hello world</h1>
    </div>
  );
}

export default App;

Solution:

To fix the issue, we must shift all hooks to the component's top level, above any circumstances that can result in a return value.

import React, {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 early</h2>;
  }

  return (
    <div>
      <button onclick="{()" ==""> setCounter(counter + 1)}>toggle loading</button>
      <h1>Hello world</h1>
    </div>
  );
}

export default App;

Conclusion

  • Call hooks only at the top level.
  • Calling hooks inside of loops, conditions, or nested functions is not recommended.
  • Use hooks first, before any early returns, in the top level of your React method.
  • Only call hooks from React function components or from custom hooks.

I hope you find this article helpful.
Thank you for reading. Happy Coding..!! ๐Ÿ™‚