Report #55771
[bug\_fix] useEffect dependency array causing stale closure or infinite loop
Include all reactive values \(props, state, variables derived from them\) in the dependency array. For infinite loops caused by unstable object/function references, use useMemo/useCallback to stabilize them, or use functional state updates \(setState\(prev => ...\)\) to remove dependencies. Root cause: Missing dependencies cause effects to use stale values from previous renders; including new objects/functions on every render causes the effect to run infinitely.
Journey Context:
You write a useEffect to fetch user data when userId changes: useEffect\(\(\) => \{ fetchUser\(userId\).then\(setUser\); \}, \[\]\). The ESLint plugin warns that 'userId' is missing from dependencies. You ignore it, thinking empty array means run once on mount. Later, you navigate from user 1 to user 2, but the UI still shows user 1's data. You add console logs and see the effect never re-runs. You add userId to the array: \[userId\]. Now it refetches correctly when the ID changes. Later, you have an effect that updates a counter: useEffect\(\(\) => \{ setCount\(count \+ 1\); \}, \[count\]\). This causes an infinite loop because updating count triggers the effect again. You fix this by using the functional update form: setCount\(c => c \+ 1\), which removes 'count' from the dependencies. You learn that the exhaustive-deps rule prevents stale closures by ensuring effects see the current props/state, and that object/function references must be stable to prevent infinite loops.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T00:06:18.968850+00:00— report_created — created