tezvyn:

What is a stale closure in React hooks?

AI-drafted, machine-checkedSource: dmitripavlutin.comadvanced
What is a stale closure in React hooks?

Tests closures and hook dependencies. A strong answer defines stale closure as capturing an outdated variable, shows a useEffect interval with stale state, and fixes it with dependencies and cleanup. Red flag: omitting cleanup or using refs blindly.

WHAT THIS TESTS: This question tests whether you understand that React hooks rely on JavaScript closures and that each render has its own props and state snapshot. The interviewer wants to see if you can explain why a callback created in one render might reference stale values after state updates, whether you know how to use the dependency array and cleanup functions correctly, and whether you understand the mental model of closures over constants rather than live variables.

A GOOD ANSWER COVERS: First, define a stale closure as a function that captures a variable from a specific render and does not see subsequent updates because that variable is a constant in the closure scope. Second, provide a concrete code example such as a useEffect with an empty dependency array that calls setInterval to log a count state variable; because the effect runs only once, the interval callback closes over the initial count value and logs it forever. Third, explain the fix by adding the state variable to the dependency array so the effect recreates the interval with the fresh value, and return a cleanup function that clears the interval before re-running to avoid duplicate timers. Fourth, mention that eslint-plugin-react-hooks helps catch missing dependencies automatically and prevents this class of bug.

COMMON WRONG ANSWERS: A red flag is suggesting useRef as the primary fix without explaining that refs are mutable and do not trigger re-renders. Another red flag is omitting the cleanup function entirely, which causes interval leaks and duplicate timers. Some candidates incorrectly claim that using the functional update form of setState alone fixes the stale closure in side effects; while functional updates help inside setState, they do not refresh closures inside intervals or event listeners.

LIKELY FOLLOW-UPS: The interviewer may ask how you would handle a rapidly changing value without tearing down and recreating an interval on every render. They might also ask about the difference between closures in useEffect versus useCallback, or how useRef can be used intentionally to hold a mutable value when you truly want to avoid re-subscription.

ONE CONCRETE EXAMPLE: Imagine a WatchCount component with const [count, setCount] = useState(0) and a useEffect that sets up setInterval to console.log(count) every 2 seconds with an empty dependency array. After the user clicks Increase three times, the UI shows three but the console still logs zero because the interval callback closed over count from the first render. The fix is to add count to the dependency array and return a cleanup function that calls clearInterval(id). This ensures the interval is reset with the current count whenever count changes.

Source: dmitripavlutin.com

Read the original → dmitripavlutin.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.