Explain why React Hooks must be called unconditionally and in the same order, how React internally matches Hook calls to state slots, and what breaks when that order changes. Hooks rely on call order, so violations cause subtle bugs. Test with lint rules and ensure stable hook order.
Why do Hooks have rules? What breaks if you call Hooks conditionally?
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
Short answer
Hooks have rules because React does not identify Hooks by name. It identifies them by call order. If you call Hooks conditionally, the order changes between renders, and React starts attaching the wrong state/effect/memo to the wrong Hook call.
The mental model
Internally, React stores Hooks for a component in something like an array and uses a pointer while rendering:useState → slot 0useEffect → slot 1useMemo → slot 2
On every render, React assumes: "The first Hook call is the same Hook as last time. The second Hook call is the same Hook as last time."
So the only thing that matters is: the order of Hook calls must be identical on every render.
function Example({ showExtra }) {
const [count, setCount] = useState(0); // Hook slot 0
if (showExtra) {
const [flag, setFlag] = useState(false); // Hook slot 1 (sometimes!)
}
const [name, setName] = useState('Alice'); // Hook slot 1 or 2 🤯
}
What breaks here?
When showExtra is false, the second useState is skipped. That means the name state now occupies slot 1 instead of slot 2.
On the next render when showExtra becomes true, React thinks:
• slot 1 = flag state
• slot 2 = name state
But previously:
• slot 1 was actually name state 😬
So now React mixes up states. Values jump between variables. Effects attach to the wrong logic. Everything becomes silently wrong.
Rule | Why it exists | What breaks if you violate it |
|---|---|---|
Only call Hooks at the top level | Guarantees stable call order | State/effects shift between variables |
Never call Hooks conditionally | Ensures same Hooks run every render | Hooks get mismatched to wrong slots |
Only call Hooks from components or custom Hooks | Ensures React controls render lifecycle | React cannot track Hook state correctly |
Important insight
This is not a "style rule". This is a fundamental constraint of how Hooks are implemented. React could have designed a more complex system using keys or IDs, but that would make Hooks slower, more complex, and harder to optimize.
How you should write conditional logic instead
Call Hooks unconditionally, and put the condition inside the Hook logic:
function Example({ showExtra }) {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
const [name, setName] = useState('Alice');
useEffect(() => {
if (!showExtra) return;
// conditional behavior goes here
}, [showExtra]);
}
Interview framing
Say it like this:
"React tracks Hooks by call order, not by name. If you call Hooks conditionally, the order changes between renders, so React attaches state and effects to the wrong Hook. The Rules of Hooks exist to guarantee stable ordering."
Practical scenario
A hook is called inside a conditional and breaks state order across renders.
Common pitfalls
- Calling hooks inside loops or conditionals.
- Using hooks in non-component functions.
- Suppressing lint rules and masking bugs.
Rules enforce consistency. Test with eslint-plugin-react-hooks and avoid conditional calls.
Hooks must be called in the same order on every render. React relies on call order to map Hook calls to internal state slots. Conditional Hooks break this mapping, causing state and effects to shift between variables and produce unpredictable bugs.