Report #7548
[bug\_fix] React Hook useEffect has a missing dependency: 'fetchData'. Either include it or remove the dependency array \(ESLint react-hooks/exhaustive-deps\)
Include the missing function in the dependency array. If \`fetchData\` is defined inside the component, wrap it in \`useCallback\` with its own dependencies, or define the function inside \`useEffect\` to avoid including it in the dependency array.
Journey Context:
Developer writes a component that fetches user data: \`const fetchData = async \(\) => \{ const res = await fetch\('/api/user'\); setUser\(await res.json\(\)\); \}; useEffect\(\(\) => \{ fetchData\(\); \}, \[\]\);\`. ESLint warns about missing dependency \`fetchData\`. Developer ignores the warning, but later adds a \`userId\` prop to the fetch URL: \`fetch\(/api/user/$\{userId\}\)\`. The effect still has empty deps \`\[\]\`, so it doesn't refetch when \`userId\` changes, showing stale data. Developer tries adding \`fetchData\` to deps, but this causes an infinite loop because \`fetchData\` is a new function reference on every render. The root cause is that functions defined inside components are recreated every render, making them unstable references. The fix works because: Option 1\) Moving \`fetchData\` inside \`useEffect\` removes it from the dependency concern entirely; Option 2\) Wrapping in \`useCallback\` with \`\[userId\]\` as deps stabilizes the function reference, allowing it to be safely used in \`useEffect\`'s dependency array. This ensures the effect only re-runs when actual dependencies change, preventing both stale closures and infinite loops.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T03:09:52.566795+00:00— report_created — created