React Hooks Interview Questions
The React Hooks questions frontend interviews actually ask — the Rules of Hooks, useEffect dependencies, useMemo vs useCallback, and stale closures.
React Hooks Interview Questions
Hooks questions in frontend interviews aren't usually about syntax — anyone can look up useState's signature. They're testing whether you understand why the rules exist and what breaks when you don't follow them. This complements our frontend JavaScript interview questions and the event loop, explained, since hook behavior leans on both.
The Rules of Hooks, and why they exist
React's own documentation states the rule plainly: only call Hooks at the top level of a function component or a custom Hook — never inside conditions, loops, or after an early return.
The why is what interviewers actually want: React tracks each component's Hooks by call order, not by name. useState doesn't know which state it's returning by looking at a variable name — it relies on being the, say, third Hook called on every single render, in the same order, every time. Wrap a useState call in an if, and on a render where the condition is false, every Hook after it shifts up one slot and starts reading the wrong state. That's the actual bug the rule prevents, not just a style preference.
// Breaks Hook order on renders where `isLoggedIn` is false
if (isLoggedIn) {
const [name, setName] = useState('');
}
const [count, setCount] = useState(0); // shifts slots depending on the condition above
useEffect and the dependency array
What does an empty dependency array ([]) actually mean?
"Run this effect once, after the first render, and clean up once when the component unmounts." It does not mean "run only on mount and never re-sync" if the effect's body references props or state — that's how you get a stale closure: the effect captured the first render's values and never sees updates.
What's a stale closure, concretely?
function Timer({ step }) {
useEffect(() => {
const id = setInterval(() => {
console.log(step); // always logs the FIRST render's `step`, forever
}, 1000);
return () => clearInterval(id);
}, []); // `step` is used inside but missing from the dependency array
}
The interval's callback closes over the step value from the render where the effect was created. Since the dependency array is [], the effect never re-runs to create a new interval with the current step — so it logs the original value forever, even after step changes.
How do you fix it?
Either add step to the dependency array (so the effect re-runs and creates a fresh interval when step changes), or use a ref for values you need to read without triggering a re-run.
useMemo vs. useCallback
Both exist to skip expensive work between renders by comparing dependencies — the difference is only what they return:
useMemo(fn, deps)memoizes the return value offn— use it for an expensive computed value (filtering a large list, a derived object).useCallback(fn, deps)memoizes the function reference itself — use it when you're passing a callback to a child that's wrapped inReact.memo, so the child doesn't re-render just because a new function instance was created.
useCallback(fn, deps) is equivalent to useMemo(() => fn, deps) — it's really useMemo specialized for functions, not a separate mechanism. Used correctly, both are about avoiding wasted render work — the same concern behind Core Web Vitals' INP metric.
Custom Hooks
What actually makes something a "custom Hook," rather than just a function?
Nothing except the use naming convention and the fact that it calls other Hooks internally. React's linter (eslint-plugin-react-hooks) uses the use prefix to know which functions to apply the Rules of Hooks to — a function named getUser that calls useState internally won't get linted for Hook-order violations, but a function named useUser will.
Can a custom Hook call another custom Hook?
Yes — Hooks composing other Hooks is the entire point of custom Hooks. They're just called during the same render as the component using them, so the Rules of Hooks still apply at every level.
Practice these with real, sandboxed tests
Explaining a hook out loud in an interview is a different skill from reciting its definition. Frontend Interview Prep runs coding challenges with real sandboxed tests, so you can check whether your mental model of dependency arrays and closures actually holds up in code, not just in explanation.
Frequently asked questions
Why can't Hooks be called conditionally?
Because React identifies each Hook by its call order within a component, not by name. A conditional Hook call changes how many Hooks run on a given render, which shifts every subsequent Hook to the wrong internal slot.
What is a stale closure in the context of useEffect?
When an effect's callback references a prop or state value but that value is missing from the dependency array, the callback keeps referencing whatever that value was on the render the effect was created — it never sees later updates unless the effect re-runs.
What's the difference between useMemo and useCallback?
useMemo memoizes a computed return value; useCallback memoizes a function reference. useCallback(fn, deps) behaves the same as useMemo(() => fn, deps) — they're the same underlying mechanism applied to different things.
Practise coding challenges with real, sandboxed tests, free.
Free to use — no upload required to get started.
Open Frontend Interview PrepBrush up on the JS underneath hooks — read the guide.