Report #97663
[bug\_fix] Stale closure in \`useEffect\` due to missing dependencies
Include all reactive values used inside the effect in the dependency array. If the effect uses a function from props, wrap it in \`useCallback\` or use the \`useEffectEvent\` hook \(React 19\+\). Example: \`useEffect\(\(\) => \{ fetchData\(id\); \}, \[id\]\)\` instead of an empty array.
Journey Context:
I was fetching search results on a product listing page. The \`useEffect\` had an empty dependency array because I only wanted to fetch once on mount. But the \`query\` variable \(from URL params\) changed when the user typed a new search. The results never updated. I logged inside the effect and saw the old query value. That's because the effect closure captured the initial \`query\` value and never re-ran when \`query\` changed. The React linting tool \(\`eslint-plugin-react-hooks\`\) had warned me about missing dependencies, but I ignored it thinking 'I only want to run on mount'. The real root cause: React effects run after render, but they close over the values from the render where they were created. If a dependency changes, the effect must re-run to pick up the new value. The fix was to add \`query\` to the dependency array, and also add a condition to avoid an extra call on mount \(or use a debounce\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-25T15:49:19.057739+00:00— report_created — created