Frontend bugs (Stale Closures)

Why your React interval is counting 0, 0, 0, 0 instead of 1, 2, 3.

The idea

A Stale Closure is a classic React hooks bug. In Javascript, functions "remember" the variables from the exact moment they were created. If you create a `setInterval` when `count` is 0, the interval's function will forever see `count` as 0.

When the interval runs `setCount(count + 1)`, it evaluates to `setCount(0 + 1)`, setting it to 1. The next tick, it runs `setCount(0 + 1)` again! To fix it, you must use the functional updater `setCount(prev => prev + 1)`, which asks React for the current state, bypassing the closure's old memory.

Closure's Memory (count)
0
React Actual State
0
Interval executes: setCount(0 + 1)
Initial render. The interval is created while count is 0.

How it works (Functional Updates)

// BAD: Stale Closure
useEffect(() => {
  const id = setInterval(() => {
    // "count" is locked to the value it had on first render (0).
    setCount(count + 1); 
  }, 1000);
  return () => clearInterval(id);
}, []); // Empty dependency array traps the old value!


// GOOD: Functional Updater
useEffect(() => {
  const id = setInterval(() => {
    // Instead of reading the variable, pass a function!
    // React guarantees 'prev' is always the absolute latest state.
    setCount(prev => prev + 1);
  }, 1000);
  return () => clearInterval(id);
}, []);