useEffect Missing Dependency
React JavaScript Framework
Severity: MinorWhat Does This Error Mean?
This React warning means your useEffect hook uses a variable or function from the component scope but has not listed it in the dependency array. React's exhaustive-deps ESLint rule warns you because if the value changes, your effect will not re-run with the new value — causing stale data bugs. The fix is to add the missing variable to the dependency array, or restructure the code so the dependency is not needed. This warning prevents subtle bugs that are very hard to debug later.
Affected Models
- React 17
- React 18
- React 19
- Create React App
- Next.js
Common Causes
- A variable used inside useEffect is not listed in the dependency array, so the effect runs with a stale (old) value of it
- A function defined in the component body is called inside useEffect but not listed as a dependency
- An async function or callback captures a variable at creation time and the dependency array is empty
- The developer intentionally left the dependency array empty to run the effect only once, but the effect uses values that change
- A prop or state variable is read inside useEffect without being declared as a dependency
How to Fix It
-
Read the warning message carefully — it tells you exactly which dependency is missing. Example: 'React Hook useEffect has a missing dependency: userId. Either include it or remove the dependency array.'
The ESLint rule is named react-hooks/exhaustive-deps. Ensure it is enabled in your ESLint configuration for all warnings to show in your editor.
-
Add the missing variable to the useEffect dependency array. Example: change useEffect(() => { fetchUser(userId); }, []) to useEffect(() => { fetchUser(userId); }, [userId]).
Adding the dependency means the effect re-runs whenever userId changes — which is usually the correct behavior.
-
If you want the effect to run only once (on mount), ensure the code inside truly does not depend on changing values. Use refs or move constants outside the component to eliminate false dependencies.
If a value is used but you genuinely do not want the effect to re-run when it changes, store it in a useRef — ref.current does not trigger re-renders or dependency warnings.
-
If a function is the missing dependency, move the function definition inside the useEffect callback or wrap it in useCallback(). Functions defined in the component body are recreated on every render and will cause infinite loops if added as dependencies without memoization.
useCallback(myFunction, [dep]) memoizes the function and gives it a stable reference that can safely be added to a dependency array.
-
Use the ESLint autofix feature. In VS Code, hover over the yellow warning squiggle on the useEffect line > Quick Fix > Add missing dependencies. This automatically adds all detected missing dependencies.
Review the autofix result carefully before committing — it may add more dependencies than you intended and could change your effect's behavior.
When to Call a Professional
This is a code quality warning about potential bugs — no external help needed. The fix is made entirely in your source code. Use the react-hooks ESLint plugin (included with Create React App and most React setups) for automatic detection of all missing dependencies.
Frequently Asked Questions
Is it safe to disable the exhaustive-deps warning with an eslint-disable comment?
Technically yes, but it is strongly discouraged. Disabling the warning suppresses it without fixing the underlying stale closure bug. The code appears to work but can produce subtle, hard-to-debug issues when values change unexpectedly. Use the disable comment only as a last resort when you have a deliberate, well-understood reason — and add a code comment explaining why.
Why does adding a function to the dependency array cause an infinite loop?
Functions defined in a component body are recreated on every render. If you add a function to useEffect's dependency array, the effect sees a 'new' function on every render and runs again, which triggers a re-render, which creates a new function, which runs the effect again — forever. Fix this by wrapping the function with useCallback() so it only changes when its own dependencies change.
What is a stale closure bug in React?
A stale closure happens when a function (like a useEffect callback) captures a variable's value at creation time but the variable later changes. The function still sees the old value because it closed over it. This is why React warns about missing dependencies — if userId was 1 when the effect was created and then changed to 2, an effect with [] will still use userId = 1 forever. Adding userId to the dependency array ensures the effect re-runs with the current value.