← Frontend interview questions
React Hooks Interview Questions
Hooks interviews rarely stop at "what is useEffect?" anymore. They wander into how you structure side-effects so they are cancellable, how you avoid stale closures without sprinkling eslint-disable comments, and when a custom hook is a clarity win versus an abstraction tax. The bar at four-plus years is architectural: can you keep data flow obvious for the next engineer who opens the file at 9 p.m. during an outage?
The dependency conversation
Be ready to defend what belongs in the dependency array—and what should not be there because you stabilized it with useCallback/useMemo or lifted state. Interviewers like hearing about AbortController in data-fetching effects, empty dependency arrays that are intentional vs accidental, and how you test async effects without flakiness. Pretending exhaustive-deps is always wrong or always right will sound junior; nuance sounds senior.
Custom hooks that earn their rent
- They hide imperative DOM or browser APIs behind declarative component code.
- They deduplicate logic three teams were copy-pasting—with tests that lock behavior.
- They expose a small surface: return shape is easy to mock in tests and Storybook.
Connect hooks to the bigger rendering picture
After this, read Virtual DOM and reconciliation so you can explain when reducing re-renders mattered for your users versus when you optimized for your own curiosity. One concrete profile-before-and-after story beats ten minutes of API trivia.
Hook-shaped problems from Azure auth and data clients
Refresh-on-focus after MSAL / Entra ID token expiry
useEffect(() => {
const onFocus = () => {
if (msalInstance.getActiveAccount()) {
acquireTokenSilent(scopes).then(setAccessToken).catch(promptLogin);
}
};
window.addEventListener('focus', onFocus);
return () => window.removeEventListener('focus', onFocus);
}, [scopes]);Users alt-tab back to your Azure Static Web App and suddenly every Graph call is 401. The hook pattern—listen, refresh, cleanup—is classic effect hygiene. In interviews, say how you avoid refresh storms (debounce, single-flight) and how you test token edge cases.
Questions with sample answers
These are interview-ready outlines—sound human by swapping in your own metrics, team names, and war stories. The examples are generic on purpose so you can map them to what you actually shipped.
Primary prompt
Implement a hook useDebouncedValue(value, ms) and explain cleanup on unmount.
Use
useEffectthat sets a timeout to update debounced state whenvaluechanges; cleanup clears timeout on unmount or before next run. AlternativelyuseDeferredValuefor React 18+ if semantics fit.function useDebouncedValue<T>(value: T, ms: number): T { const [d, setD] = useState(value); useEffect(() => { const t = setTimeout(() => setD(value), ms); return () => clearTimeout(t); }, [value, ms]); return d; }Primary prompt
A parent passes an inline function; a memoized child re-renders every time—fix it without blaming React.
Stabilize callback in parent with
useCallback(correct deps) or move handler to module scope; fix parent first—childmemoonly helps when props are referentially stable.Example:
<Row onOpen={() => open(id)} />→ passidand stableonOpenor wrap Row to callopen(id)inside withuseCallbackper id via map factory carefully.Primary prompt
How do you fetch data on mount with cancellation when the route changes quickly?
AbortControllerin effect: abort previous fetch when deps change or on cleanup; ignore stale responses with a flag if needed—but prefer abort.Primary prompt
Rules of Hooks were violated in a PR—how do you catch that in review and in CI?
ESLint
react-hooks/rules-of-hooksandexhaustive-depsin CI blocking; code review checklist; educate on conditional hooks anti-pattern; Storybook/tests that mount alternate branches.
Follow-ups interviewers often ask
Expect nested "why?" questions—brief answers here; expand with your production defaults.
Follow-up
When is useRef the right tool vs useState for values that should not trigger render?
Refs for timers, latest callback in effects, DOM nodes, mutable counters that shouldn't re-render—state when UI must reflect value.
Follow-up
How do you test effects that depend on changing props without infinite loops in tests?
waitForfrom RTL, control prop changes across rerenders, mock fetch with MSW, use fake timers carefully; isolate effect with minimal wrapper component.Follow-up
What is your stance on useEffect for derived state—when is it a smell?
Compute during render if synchronous from props/state; effect only for synchronization with external systems— otherwise you risk flicker and loops.
Follow-up
How do custom hooks compose without becoming a "god hook"?
Single responsibility:
useUser,useOrders; compose in container; avoid 15-return-value hooks—return small objects.Follow-up
Server Components: which hooks disappear or move—how do you explain that to the team?
No useState/useEffect in RSC—data fetch on server; client boundaries for interactivity; shared types across boundary; migration incremental by route.