Closures and useState Aren't Two Topics: You Only Learned Half the Scope Chain
A developer who memorizes closure definitions and React hooks as separate facts can still watch a counter freeze at 1 and have no explanation. Treating them as one scope-chain mechanism makes the failure mode obvious and the fix deterministic: reach for a functional update or put the value into the dependency array.
Interview prep usually files closures and React state under separate flashcards: define a closure, then memorize hook rules. The five demos in a Xiaomi frontend review outline put both on one chain. Lexical scope decides where a variable is looked up, starting from where the function is written, not where it is called. A closure exists when an inner function is carried outside its defining scope; the engine moves the variables it references into a Context object on the heap. The stack frame dies normally while the variables live on, which is why closure leaks grow the heap, and why the only leak question that matters is whether the holder is a global or local variable.
React follows the same model. A component is a function; each render is a fresh call with its own local snapshot. An effect with an empty dependency array creates its timer once in the first render, and the callback keeps reading `count = 0`. Calling `setCount(count + 1)` every second always computes `0 + 1`, React sees the same value, and the UI stays at `Count: 1`. Switching to `setCount(prev => prev + 1)` pulls the latest value from React's update queue instead of the stale snapshot. That same snapshot mechanism produces the `useState` rules: initial values run only on first render, updates are batched, and any update that depends on previous state has to use the functional form.
The same code starts misbehaving when `setInterval` becomes `useEffect`, which is the strongest clue that closures and React state are not separate topics: both fail at the boundary where a callback outlives the render that created it.
Heap-versus-stack wording changes the diagnostic: if closure variables stayed on the stack, a popped frame would wipe them and closures could not outlive their creator; naming the heap Context makes leak diagnosis a question of who still holds the closure.
A single yes/no test, whether the inner function gets carried out, explains heap persistence, a React counter stuck at 1, and global memory retention. That compression into three observable outcomes is what makes it useful in an interview.
The example of the counter getting stuck at 1 is explained very clearly: the callback in the empty dependency array keeps holding the count from the first render. The functional update line is indeed the most convenient.