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.
Also appears as
- Rendered fewer hooks than expected. This may be caused by an accidental early return statement.
- React has detected a change in the order of Hooks called by Profile. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://react.dev/link/rules-of-hooks
- Minified React error #310; visit https://react.dev/errors/310 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 "Rendered more hooks than during the previous render." Find the component where a hook runs only some of the time: after an early return, inside an if, &&, ternary, or loop, or inside a component that is called as a plain function. Move every hook to the top of the component above the first return, and move the condition inside the hook, for example inside the effect or as a query’s enabled option. Don’t disable the rules-of-hooks lint rule.
Paste into Layerwise or any AI coding tool.
What it means
React doesn’t know your hooks by name. It remembers them by position: the first hook in a component is slot one, the next is slot two, and so on. That only works if the component calls the same hooks in the same order on every render.
The usual cause is an early return above a hook, such as if (!user) return <Spinner />; followed by useEffect(...). The first render returns early and calls fewer hooks. Once the data arrives, the component reaches the extra hook, and React finds a slot it has never seen.
The fix is always the same: put every hook above the first return, outside any condition or loop. Move the condition inside the hook instead, for example inside the effect or into a query’s enabled option.
Common causes
- An early return for loading, an error, or a missing user sits above a
useState,useEffect, or custom hook. - A hook is called inside an
if, after&&, or in one branch of a ternary, so it runs only some of the time. - A hook is called inside a loop or
.map()whose length changes between renders. - A component that uses hooks is called like a function, as in
{open && Panel()}, so its hooks become part of the parent’s list only some of the time.
How to fix it
- Open the component in the error and find its first
returnand every condition that comes before a hook. - Move all hooks to the top of the component, above any early return.
- Move conditions inside the hooks: check them inside
useEffect, or pass an option likeenabled: Boolean(userId)to a data-fetching hook. - Render components as elements,
<Panel />, so each one keeps its own hooks. - Turn on the
react-hooks/rules-of-hooksESLint rule so the editor flags this while you edit.
Example fix
import { useEffect } from 'react';
type User = { name: string };
export function Profile({ user }: { user?: User }) {
// Every hook runs on every render, before any early return.
useEffect(() => {
if (user) document.title = user.name;
}, [user]);
if (!user) return <p>Loading...</p>;
return <h1>{user.name}</h1>;
}Related errors
All errorsInvalid hook call
A hook such as useState ran somewhere React can’t track it, or the app loaded two copies of React that don’t know about each other.
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.
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.
Each child in a list should have a unique "key" prop
A list rendered with map gave its items no stable ID, so React can’t tell which item is which when the list changes.
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.