Rules of Hooks
Call hooks only at the top level and only from React functions — why stable call order matters.
The two rules 🎯#
- Only call hooks at the top level. Never inside conditions, loops, nested functions, or after an early
return. - Only call hooks from React functions — function components or custom hooks (names starting with
use). Not from regular JS functions or class components.
// ⚠️ conditional hook — breaks call order
function Bad({ show }) {
if (show) {
const [x, setX] = useState(0); // sometimes called, sometimes not
}
}
// 🟢 hook at top level, condition inside
function Good({ show }) {
const [x, setX] = useState(0);
if (show) { /* use x */ }
}
Why: hooks rely on call order 🎯#
React does not identify hooks by name — it identifies them by the order they're called in each render. State lives in a per-component list indexed by call position. The first useState is slot 0, the second is slot 1, and so on. React just walks the list in sequence.
flowchart TD
R["Render component"] --> H1["useState -> slot 0"]
H1 --> H2["useState -> slot 1"]
H2 --> H3["useEffect -> slot 2"]
H3 --> N["Next render must hit the same slots in the same order"]
If a hook is called conditionally, the slots shift between renders: slot 1 on render A becomes slot 0's data on render B, so state gets attached to the wrong hook and React reads garbage. Keeping every hook unconditional and in the same order guarantees each render lines up with the previous one.
| Render 1 (show=true) | Render 2 (show=false) | Result |
|---|---|---|
| slot0: name state | slot0: name state | ok |
| slot1: conditional state | (skipped) | ⚠️ slots misalign after here |
| slot2: effect | slot1: effect | wrong slot |
Enforcement#
🟢 Use eslint-plugin-react-hooks (bundled in Create React App / Next.js / Vite templates):
rules-of-hooks— errors on conditional/looped/nested hook calls.exhaustive-deps— warns when an effect/callback dependency array is incomplete.
These catch the mistakes statically before they become runtime state bugs.
Interview Q&A#
Q1. What are the two rules of hooks? Call hooks only at the top level (no conditions, loops, or nested functions), and only from React function components or custom hooks.
Q2. Why can't hooks be conditional? React tracks hook state by call order, not by name. Skipping a hook shifts every subsequent hook's slot, so state attaches to the wrong hook on the next render.
Q3. Where can you legally call a hook?
Inside a function component body or inside another custom hook (a use-prefixed function). Never in event handlers, plain functions, or class components.
Q4. How is the rule enforced?
eslint-plugin-react-hooks provides rules-of-hooks and exhaustive-deps lint rules that flag violations at build time.
Q5. Can you put a condition inside a hook?
Yes — the hook call must be unconditional, but the logic inside it (or inside the effect body) can be conditional. Move the if inside, not around, the hook.