Published at

Rendered more(fewer) hooks than expected

Rendered more(fewer) hooks than expected

Learn how to resolve 'Rendered more hooks than during the previous render

Table of Contents

React hooks are a powerful tool for managing state and side effects in functional components. However, they can be tricky to use correctly, and it is easy to make mistakes that can lead to errors. One common error is to render more or fewer hooks than expected.

Problem

In the following example code, the problem is that the useMemo hook is rendered only when the counter state is less than 3. This means that if the initial value of counter is 4 or greater, the useMemo hook will not be rendered at all. However, if the user clicks the decrement button until counter is less than 3, the useMemo hook will be rendered on the next re-render. This causes React to throw an error because the number of rendered hooks has changed.

import React from 'react';
import './style.css';
import { useState, useMemo } from 'react';

export default function App() {
  const [counter, setCounter] = useState(6);

  if (counter > 3)
    return (
      <div>
        {counter}
        <p>
          <button onClick={() => setCounter((prv) => prv - 1)}>-</button>
        </p>
      </div>
    );

  const doubled = useMemo(() => counter * 2);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      doubled:{doubled} <br />
      initial: {counter}
      <p>
        <button onClick={() => setCounter((prv) => prv + 1)}>+</button>
      </p>
    </div>
  );
}

If the initial value of counter is 4 or greater, and the user clicks the decrement button until counter is less than 3, the following error will be thrown:

Error: Rendered more hooks than during the previous render. This may be caused by an accidental early return statement.

Solution

The solution to this problem is to move the useMemo hook to the top of the component, before the conditional statement. This will ensure that the useMemo hook is always rendered, regardless of the value of counter.

import React from 'react';
import './style.css';
import { useState, useMemo } from 'react';

export default function App() {
  const [counter, setCounter] = useState(6);
  const doubled = useMemo(() => counter * 2);

  if (counter > 3)
    return (
      <div>
        {counter}
        <p>
          <button onClick={() => setCounter((prv) => prv - 1)}>-</button>
        </p>
      </div>
    );

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      doubled:{doubled} <br />
      initial: {counter}
      <p>
        <button onClick={() => setCounter((prv) => prv + 1)}>+</button>
      </p>
    </div>
  );
}

With this change, the useMemo hook will always be rendered, and the error will be avoided.

Conclusion

React hook error handling can be tricky, but it is important to understand how to handle common errors correctly. By following the tips above, you can write React JS applications that are more robust and reliable.

Sharing is caring!