yoklainterview sim

Frontend React Hooks State Interview Questions

75 verified Frontend React Hooks State interview questions — solve with answers, learn from explanations, test yourself in a real simulation.

Try the real simulation →

Sample questions

React Hooks StateDifficulty 2
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => {
      setCount(count + 1);
      setCount(count + 1);
    }}>{count}</button>
  );
}

Starting from count = 0, the button is clicked once. What does it show afterward?
  • a1
  • b2
  • cNaN
  • d0, unchanged
Explanation:Both calls read count from the same render's snapshot, which is 0 for the whole event. So both calls are effectively setCount(0 + 1); React does not re-run the function body between them, it just schedules the same replacement value twice. The result is 1, not 2. The updater-function form (c => c + 1) is what would make each call build on the previous one.
React Hooks StateDifficulty 2
function ScoreBoard() {
  const [score, setScore] = useState(0);
  const handleClick = () => {
    setTimeout(() => setScore(s => s + 1), 0);
    setTimeout(() => setScore(s => s + 1), 0);
  };
  return <button onClick={handleClick}>{score}</button>;
}

Starting from score = 0, the button is clicked once. After both setTimeout callbacks have fired, what does it show?
  • a1
  • b2
  • cNaN
  • d0, unchanged
Explanation:Each setTimeout callback runs later, on its own turn of the event loop, well after handleClick's own closure over score is stale. Because each call uses the updater form s => s + 1, React applies it to whatever the latest state is at the time it runs, not to the score variable captured when handleClick was defined — so the first callback turns 0 into 1, and the second turns that 1 into 2. Had these instead read the outer score directly (setScore(score + 1)), both callbacks would have closed over the same stale 0 and the result would incorrectly stay 1. Verified in React 19 (jsdom): after mounting the button shows 0; clicking it and letting both timeouts run shows 2.
React Hooks StateDifficulty 2
A button's click handler needs to reliably add 1 to a counter, and it may sometimes call the increment logic more than once within the same event (e.g. a shared helper called twice). Which practice avoids losing one of the increments?
  • aCalling setCount(count + 1) repeatedly, relying on the outer count variable each time
  • bRemoving the count state entirely and using a plain module-level variable instead
  • cUsing the updater-function form, setCount(c => c + 1), for each call
  • dRe-mounting the component after every increment so state starts fresh
Explanation:The updater form always operates on the most recently queued value, so stacking several calls in the same event correctly accumulates. Reading the outer count variable repeatedly reuses the same render's snapshot and silently drops updates, which is the bug this practice avoids.
React Hooks StateDifficulty 2
function Page() {
  const [data] = useState(computeExpensiveDefault());
  return <div>{data}</div>;
}

If Page re-renders 3 times (e.g. because its parent re-renders), how many times does computeExpensiveDefault() actually run?
  • aOnce, only on the first render
  • bZero times, React caches the argument expression automatically
  • cOnce, only on the last render
  • dOnce per render, so 3 times total
Explanation:computeExpensiveDefault() is a plain JavaScript expression sitting in the argument position; JavaScript evaluates it every time the component function runs, regardless of whether useState ends up using the result. useState only USES the value on the very first render and throws away the result on later ones — but it does not stop the expression itself from being evaluated. That's exactly why lazy init, useState(() => computeExpensiveDefault()), exists.
React Hooks StateDifficulty 1
You have an expensive calculation that should run exactly once, on the component's first render, to produce the initial state. Which is the correct useState usage?
  • auseState(() => computeExpensiveDefault())
  • buseState(computeExpensiveDefault())
  • cuseState(useMemo(computeExpensiveDefault))
  • duseState(null), then call setState inside a useEffect
Explanation:Passing a function to useState is the lazy-initializer form: React calls that function only on the first render to compute the initial value, and never calls it again on later renders. Passing the already-called result (b) still evaluates the expensive call on every render even though the value is discarded.
React Hooks StateDifficulty 1
In const [value, setValue] = useState(initialValue);, on which render(s) is initialValue actually used to set the state?
  • aIt is re-evaluated and assigned to state on every render
  • bOnly on the component's very first render
  • cOnly when the component unmounts
  • dOnly if initialValue was itself derived from a prop
Explanation:React only reads the argument passed to useState the first time that hook call runs for a given component instance; on every subsequent render, useState returns the stored state and ignores whatever expression is currently sitting in the argument position.

Test yourself against the 2925-question Frontend bank.

Start interview