Too many re-renders

A component changes its own state while it renders, so React renders it again and again until it stops the loop.

Browser console
Too many re-renders. React limits the number of renders to prevent an infinite loop.

Also appears as

  • Minified React error #301; visit https://react.dev/errors/301 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

Prompt to fix it

My React app crashes with "Too many re-renders. React limits the number of renders to prevent an infinite loop." Find the component that sets state while it renders. Look for event props that call a setter directly, such as onClick={setOpen(true)}, and setter calls in the component body or in custom hooks. Pass event handlers as functions, and replace state that only copies props with values computed during render. Don’t hide the loop with a render counter or try/catch. Tell me which line caused it.

Paste into Layerwise or any AI coding tool.

What it means

React renders a component by calling its function. If that function sets state while it runs, React has to render it again, which sets state again. After 25 rounds React stops and throws this error, and the screen usually goes blank.

The classic cause is an event prop that calls a function instead of passing it. onClick={setOpen(true)} runs setOpen during render. onClick={() => setOpen(true)} hands React a function to call later, when someone clicks.

The error names the component but not the line. Search that component for any call that starts with set and sits outside an event handler or effect, including one inside an if that copies a prop into state.

Common causes

  • An event prop calls the state setter directly, as in onClick={setCount(count + 1)}, so it runs on every render.
  • The component body calls a setter to copy a prop or a computed value into state, such as if (items) setCount(items.length).
  • A custom hook sets state during render, so every component that uses it loops.

How to fix it

  1. Open the component named in the stack trace and find every call that starts with set.
  2. Wrap setters in event props in an arrow function: onClick={() => setOpen(true)}.
  3. Delete state that only copies props or other state, and compute the value during render instead: const count = items.length.
  4. If state must change after something happens, set it in the event handler that caused it.

Example fix

import { useState } from 'react';

export function Menu({ items }: { items: string[] }) {
  const [open, setOpen] = useState(false);

  // Computed during render. Storing it in state with a setter here would loop.
  const count = items.length;

  return (
    // Pass a function. onClick={setOpen(!open)} would run during render.
    <button onClick={() => setOpen(!open)}>
      Menu ({count})
    </button>
  );
}
All errors
Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Maximum update depth exceeded

State updates kept triggering more state updates in a loop, usually through an effect or a callback, so React stopped them.

Rendered more hooks than during the previous render.

Rendered more hooks than during the previous render

A component called a different number of hooks than on its last render, usually because a hook sits after an early return or inside an if.

RangeError: Maximum call stack size exceeded

Maximum call stack size exceeded

A function kept calling itself, directly or through other functions, until JavaScript ran out of room to keep track of the calls.

Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used: - A server/client branch `if (typeof window !== 'undefined')`. - Variable input such as `Date.now()` or `Math.random()` which changes each time it's called. - Date formatting in a user's locale which doesn't match the server. - External changing data without sending a snapshot of it along with the HTML. - Invalid HTML tag nesting. It can also happen if the client has a browser extension installed which messes with the HTML before React loaded. https://react.dev/link/hydration-mismatch

Hydration failed

The HTML the server sent didn’t match what React rendered first in the browser, so React threw that part away and rebuilt it on the client.

Build with an agent that checks its work

The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.