How to fix Rendered more hooks than during the previous render in React
This error occurs when the number of React hooks called changes between renders, typically because hooks are placed inside conditions, loops, or after early returns. React requires hooks to be called in the exact same order on every render to properly track component state.
Quick fix
Fixes Rendered more hooks than during the previous render
function MyComponent({ isLoggedIn }) {
if (!isLoggedIn) {
return <Login />;
}
// ❌ This hook only runs when isLoggedIn is true
const [user, setUser] = useState(null);
return <div>{user?.name}</div>;
}- Move all hooks to the top level of your component
- Move conditional logic inside hooks instead of around them
- Extract conditional components into separate child components
- Replace direct component function calls with JSX syntax
function MyComponent({ isLoggedIn }) {if (!isLoggedIn) {return <Login />;}// ❌ This hook only runs when isLoggedIn is trueconst [user, setUser] = useState(null);return <div>{user?.name}</div>;}Rendered more hooks than during the previous render
What this error means
This error indicates that React detected a change in the number of hooks being called during a component's render cycle. React hooks (like useState, useEffect, useContext) must be called in the exact same order on every render because React tracks them using their call order in an internal linked list structure. When a hook is skipped or called conditionally on one render but not the next, React's internal tracking becomes misaligned. The framework expects the same sequence of hooks each time, and any deviation causes this error to be thrown. This is a fundamental requirement of how React's hooks system works - it relies on consistent call order rather than unique identifiers to associate each hook with its corresponding state and effects. The error message specifically means that on the current render, React encountered more hook calls than it did on the previous render, which violates the Rules of Hooks and indicates that hook calls are happening conditionally or in an inconsistent manner.
Typical symptoms
- Application crashes with "Rendered more hooks than during the previous render" error message
- Error occurs after conditional logic changes (like toggling a feature flag or authentication state)
- Component works initially but breaks when re-rendering with different props or state
- Console shows "React has detected a change in the order of Hooks" warning
- ESLint with react-hooks plugin shows warnings about conditional hook usage
- Development mode shows the error but the exact cause is unclear from the stack trace
- Error happens when returning early from a component before all hooks are called
Common causes
- Calling hooks (useState, useEffect, etc.) inside if statements or conditional blocks
- Placing hooks after an early return statement that sometimes executes and sometimes doesn't
- Using hooks inside loops or iterating over arrays to generate multiple hook calls
- Calling a component function directly (like MyComponent()) instead of using JSX (<MyComponent />)
- Nesting hooks inside callback functions or event handlers instead of at the component top level
- Conditionally rendering a component that contains hooks based on state or props
- Having different code paths that call different numbers of hooks based on runtime conditions
- Using hooks after conditional returns or throw statements that don't always execute
How to fix "Rendered more hooks than during the previous render"
Ensure all hook calls happen before any conditional logic or return statements. Hooks must always execute in the same order.
Before (incorrect):
function MyComponent({ isLoggedIn }) {
if (!isLoggedIn) {
return <Login />;
}
// ❌ This hook only runs when isLoggedIn is true
const [user, setUser] = useState(null);
return <div>{user?.name}</div>;
}After (correct):
function MyComponent({ isLoggedIn }) {
// ✅ Hook is always called at the top level
const [user, setUser] = useState(null);
if (!isLoggedIn) {
return <Login />;
}
return <div>{user?.name}</div>;
}If you need conditional behavior, place the condition inside the hook rather than conditionally calling the hook itself.
Before (incorrect):
function MyComponent({ shouldFetch }) {
if (shouldFetch) {
// ❌ Hook only called when shouldFetch is true
useEffect(() => {
fetchData();
}, []);
}
}After (correct):
function MyComponent({ shouldFetch }) {
// ✅ Hook always called, condition moved inside
useEffect(() => {
if (shouldFetch) {
fetchData();
}
}, [shouldFetch]);
}When you need to conditionally use hooks, create a separate component that always calls its hooks in a consistent order.
Before (incorrect):
function Dashboard({ userType }) {
if (userType === 'admin') {
const [stats, setStats] = useState(null); // ❌ Conditional hook
return <AdminDashboard stats={stats} />;
}
return <UserDashboard />;
}After (correct):
function AdminDashboardWrapper() {
const [stats, setStats] = useState(null); // ✅ Always called
return <AdminDashboard stats={stats} />;
}
function Dashboard({ userType }) {
if (userType === 'admin') {
return <AdminDashboardWrapper />;
}
return <UserDashboard />;
}If you're calling component functions directly instead of using JSX, this can disrupt React's render cycle and hook tracking.
Before (incorrect):
function App() {
const [count, setCount] = useState(0);
// ❌ Calling component as a function
return MyComponent({ count });
}After (correct):
function App() {
const [count, setCount] = useState(0);
// ✅ Using JSX syntax
return <MyComponent count={count} />;
}Never call hooks while iterating over arrays or in any kind of loop structure.
Before (incorrect):
function ItemList({ items }) {
return items.map(item => {
// ❌ Hook called in a loop - number changes with items.length
const [selected, setSelected] = useState(false);
return <Item key={item.id} selected={selected} />;
});
}After (correct):
function ListItem({ item }) {
// ✅ Hook in separate component
const [selected, setSelected] = useState(false);
return <Item selected={selected} />;
}
function ItemList({ items }) {
return items.map(item => (
<ListItem key={item.id} item={item} />
));
}Install and configure eslint-plugin-react-hooks to automatically detect hook rule violations during development.
npm install eslint-plugin-react-hooks --save-devAdd to your .eslintrc.json:
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}This will show errors in your editor when you violate the Rules of Hooks, catching issues before runtime.
If you're using custom hooks, ensure they also follow the Rules of Hooks and don't call hooks conditionally.
Before (incorrect):
function useAuth(requireAuth) {
if (requireAuth) {
// ❌ Conditional hook in custom hook
const user = useContext(AuthContext);
return user;
}
return null;
}After (correct):
function useAuth() {
// ✅ Always call the hook
const user = useContext(AuthContext);
return user;
}
// Use conditional logic at the call site instead
function MyComponent({ requireAuth }) {
const user = useAuth();
if (requireAuth && !user) {
return <Login />;
}
return <Dashboard />;
}Advanced notes
Why React uses call order: React's hooks implementation relies on a linked list data structure where each hook call adds a node in sequence. This design choice makes the implementation fast and memory-efficient, but requires strict ordering rules. Alternative designs using unique IDs or keys were considered but rejected due to performance overhead and developer experience concerns.
Next.js and Server Components: In Next.js 13+, be aware that Server Components cannot use hooks at all. Only Client Components (marked with 'use client') can use hooks. Mixing these patterns incorrectly can cause confusing hook errors.
Testing considerations: When writing tests, ensure your test cases exercise all code paths. A component might work in one test scenario but fail in another if hooks are conditionally called based on props or state that differ between tests.
React DevTools: The React DevTools extension can help visualize the hooks tree for a component. When debugging this error, use DevTools to inspect which hooks are being called and in what order during different renders.
Concurrent React and Suspense: With React 18's concurrent features, components may render multiple times or partially. Hook order violations become even more critical in this context as renders may be interrupted and restarted.
Prevention best practices:
- Always use the ESLint plugin for real-time feedback
- Extract complex conditional rendering into separate components
- Keep all hooks at the very top of your function body
- Use TypeScript to catch structural issues earlier
- Review custom hooks with the same scrutiny as components
Frequently asked questions
- What does "Rendered more hooks than during the previous render" mean?
- This error indicates that React detected a change in the number of hooks being called during a component's render cycle. React hooks (like useState, useEffect, useContext) must be called in the exact same order on every render because React tracks them using their call order in an internal linked list structure. When a hook is skipped or called conditionally on one render but not the next, React's internal tracking becomes misaligned.
- How do I fix "Rendered more hooks than during the previous render"?
- This error occurs when the number of React hooks called changes between renders, typically because hooks are placed inside conditions, loops, or after early returns. React requires hooks to be called in the exact same order on every render to properly track component state.
- What causes "Rendered more hooks than during the previous render"?
- Calling hooks (useState, useEffect, etc.) inside if statements or conditional blocks Placing hooks after an early return statement that sometimes executes and sometimes doesn't Using hooks inside loops or iterating over arrays to generate multiple hook calls
- Is the "Rendered more hooks than during the previous render" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- 📚React Official Documentation
- 📖React Docs: Rules of Hooks - Invalid Hook Call Warning(Official Docs)
- 📖React Docs: Rules of Hooks(Official Docs)
- 🐙
- 🐙