# React: “Rendered more hooks than during the previous render”

> React says Rendered more hooks than during the previous render: a Hook runs only on some renders, after an early return or inside a condition. How to fix it.

Canonical: https://app369.com/fix/react-rendered-more-hooks-than-during-the-previous-render/
Last updated: 2026-11-08

The screen crashes with Rendered more hooks than during the previous render, usually the moment data finishes loading or a prop changes. React matches each Hook to its state by call order. A component that calls a Hook on one render and skips it on another, most often because of an early return above it, breaks that order.

**Short answer**

Find the Hook that runs only sometimes: a useState, useEffect, useMemo or custom Hook below an if (loading) return, inside a condition, or inside a loop. Move every Hook to the top of the component, above the first return, and put the condition inside the Hook or after it. The reverse message, Rendered fewer hooks than expected, has the same cause and the same fix. If it appeared right after an edit in the dev server, reload the page once first: Fast Refresh can keep the old Hook order.

## **Why the Hook count changes, and the fix**

1. 01 ### **A Hook below an early return**
  > “Do not call Hooks after a conditional return statement.” [**React, Rules of Hooks**](https://react.dev/reference/rules/rules-of-hooks) On the first render, data is still loading and the component returns before it reaches the useMemo or useEffect below. When the data arrives, it runs that Hook too, so this render has more Hooks than the last one. Move the Hook above the return and let it handle empty data.```
// breaks: useMemo runs only after loading ends
function Orders({ orders, loading }) {
  if (loading) return <Spinner />;
  const total = useMemo(() => sum(orders), [orders]);
  return <Total value={total} />;
}

// works: every Hook runs on every render
function Orders({ orders, loading }) {
  const total = useMemo(() => sum(orders ?? []), [orders]);
  if (loading) return <Spinner />;
  return <Total value={total} />;
}
```
2. 02 ### **A Hook inside a condition or loop**
  > “Hooks rely on a stable call order on every render of the same component.” [**React, State: A Component’s Memory**](https://react.dev/learn/state-a-components-memory) if (user) { useEffect(…) } or a useState inside .map() changes the number of Hook calls whenever the condition or the list length changes. Call the Hook unconditionally and move the condition inside it, or move the list item into its own component that has its own Hooks.```
// breaks
if (user) {
  useEffect(() => track(user.id), [user]);
}

// works
useEffect(() => {
  if (user) track(user.id);
}, [user]);
```
3. 03 ### **A component called as a function**
  > “Don’t call Hooks from regular JavaScript functions.” [**React, Rules of Hooks**](https://react.dev/reference/rules/rules-of-hooks) Calling a component like renderRow(item) or Row(item) instead of rendering <Row item={item} /> runs its Hooks as part of the parent. When the number of rows changes, the parent’s Hook count changes with it. Render it as JSX so each row keeps its own Hooks.
4. 04 ### **Catch it before it ships**
  > “Additionally, a linter plugin catches most mistakes.” [**React, State: A Component’s Memory**](https://react.dev/learn/state-a-components-memory) The React Hooks ESLint plugin flags a Hook after an early return or inside a condition as you type. Turn it on, so code an AI tool wrote or you pasted in is caught in the editor instead of in production.

Checked against the vendor’s docs on November 8, 2026: [React: Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks); [React: State, a component’s memory (why Hook order matters)](https://react.dev/learn/state-a-components-memory).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

Related: [**React “Invalid hook call”**](https://app369.com/fix/react-invalid-hook-call/) · [**React “Too many re-renders”**](https://app369.com/fix/react-too-many-re-renders/) · [**React “changing an uncontrolled input to be controlled”**](https://app369.com/fix/react-changing-an-uncontrolled-input-to-be-controlled/)

Questions

## **More on this error**

<details>

<summary>**Why does it only crash after the data loads? **+</summary>

Because that is the first render that reaches the Hook below the loading check. The render before it returned early and skipped the Hook, so React sees one more Hook than last time.

</details>

<details>

<summary>**What about “Rendered fewer hooks than expected”? **+</summary>

It is the same problem the other way round: a render skipped a Hook that ran last time, often because of an early return that only triggers sometimes. Move the Hooks above every return.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)