Report #73398
[bug\_fix] Stale closure in useEffect missing dependency
Include all reactive values \(props, state, and derived variables\) used inside \`useEffect\` in the dependency array. If including a function causes infinite loops, wrap the function in \`useCallback\` with its own dependencies. If including an object causes loops, use primitive values or memoize the object with \`useMemo\`. Root cause: JavaScript closures capture values at the time of render; React only re-runs the effect when dependency values change, so missing deps cause the effect to see stale values from previous renders.
Journey Context:
You have a \`userId\` prop and fetch user data in \`useEffect\` with \`\[userId\]\` in deps. Later, you add a \`filter\` state and use it inside the fetch effect, but forget to add \`filter\` to the deps array. The UI shows stale data—clicking the filter buttons doesn't update the list. You add console logs and see \`filter\` is correct outside the effect, but inside the effect it's always the initial value. You realize the closure captured the old value at the time of the first render. You add \`filter\` to deps, but now you get an infinite loop because \`fetchData\` is recreated every render and included in deps. You then wrap \`fetchData\` in \`useCallback\` with \`\[userId, filter\]\` as its deps, then include \`fetchData\` in the effect's deps. Now the effect runs only when necessary and always sees the latest values without causing loops.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T05:47:36.018335+00:00— report_created — created