How hooks work: call order and the rules of hooks
React stores each component's hooks in a list on its fiber and matches them by call order. That is why hooks cannot be called conditionally. Plus the ESLint plugin, and why custom hooks share logic, not state.
Comes up in: React, Recruiter screen
Learn#
Imran adds if (isAdmin) { const [count, setCount] = useState(0); } to a profile form. When an admin logs in, the page crashes with “Rendered more hooks than during the previous render”. The same code worked for every other user.
React does not store hooks by name. Each component’s fiber keeps a list of hook slots, and React matches calls to slots by order: the first useState call gets slot 0, the second gets slot 1, on every render. If one render calls an extra hook first, every later hook reads the wrong slot.
That is why the rules of hooks exist: call hooks only at the top level of a component or custom hook, never inside conditions, loops, or after an early return, and only from React functions.
State
- slot 0: name = Asha
- slot 1: editing = false
Console
empty
First render: Profile calls useState('Asha'), then useState(false). React creates hook slot 0 and slot 1 on the fiber.
Read the steps as text
- First render: Profile calls useState('Asha'), then useState(false). React creates hook slot 0 and slot 1 on the fiber.
- Next render, isAdmin is true, so an extra useState(0) runs first, inside an if.
- React does not know names, only order. The first call now gets slot 0, "Asha", meant for name; the second gets false.
- Every value is shifted. In development React warns about the order; because there is now one more hook than last time, it also throws.
Predict#
Predict first
Two components both call the same custom hook useCounter(). Do they share one count?
A custom hook is a function that calls other hooks. Its state lives in the slots of whichever component calls it, so each caller gets its own. To share state, lift it up or use context or a store.
Interview angle#
Say it like this — about 30 seconds
“React keeps each component’s hooks as an ordered list on its fiber. On every render it walks that list and hands the next slot to the next hook call. Because matching is by position, not name, the calls must happen in the same order every time, which is why hooks cannot be inside conditions, loops or after early returns. The ESLint rules-of-hooks plugin catches violations. Custom hooks are just functions that call hooks, so they share logic, not state.”
Follow-up How do hooks work internally? Why can't you call them conditionally?
Follow-up How do you run a hook only sometimes?
Follow-up Why must custom hook names start with use?
Practice#
On your own
Build a tiny hooks runtime with an array of slots, the way React matches hooks by order.
Done when
useStatekeeps values across renders by slot, and its setter supports updater functions.useEffectruns only when deps change, after cleanup of the previous run.- A component that calls hooks conditionally gets values from the wrong slots, just like in React.
Remember#
Try to answer each card before you open it. Then add them to your reviews.
How does React match hook calls to stored state?
By call order, using a list of slots per component.
Why can't hooks be called inside if statements?
Skipping a call shifts every later hook to the wrong slot.
Do two components using the same custom hook share state?
No. Each call keeps its own state.
Which tool enforces the rules of hooks?
The eslint-plugin-react-hooks rules.
Go deeper
Four layers. Stop at the one your interview needs; each ends with a quick check.
The core ideaEvery round
Allowed: the top level of function components and custom hooks. Not allowed: conditions, loops, nested functions, after an early return, class components and plain helper functions.
Check yourself: Can you call a hook after an early return?
No. Then some renders call it and some do not.
How it works underneathSenior rounds
Each fiber’s memoizedState points to a linked list of hooks. While rendering, React keeps a pointer to the current hook and moves it forward with each call; useState reads its slot and applies queued updates Source: React: Rules of Hooks.
Check yourself: Where does React keep the hook list?
On the component's fiber, as a linked list in memoizedState.
Edge cases and trapsWhere people slip
The use API (RCT.05.02) is the exception: it can be called conditionally, because it reads a promise or context instead of owning a slot.
Check yourself: Is the new use() API bound by the same ordering rule?
No. use can be called inside conditions and loops.
In productionStaff-level answers
eslint-plugin-react-hooks with rules-of-hooks and exhaustive-deps Source: React: eslint-plugin-react-hooks.useSomething; each caller gets its own state.Check yourself: What does the exhaustive-deps lint rule check?
That effects and memos list every reactive value they use.
Finished the five steps? Mark it, and its cards join your reviews.
Last checked 2026-11-01. Spot a mistake? Use “Report an error” below — fixes are listed on the corrections page.
Interview questions this answers
- How do hooks work internally? Why can't you call them conditionally?