How to Fix: React Hook useEffect has a missing dependency. Either include it or remove the dependency array.
The exhaustive-deps ESLint rule warning about stale closures.
What Causes It?
You used a variable or function inside a `useEffect` or `useCallback` hook, but you didn't include it in the dependency array `[]` at the end of the hook. React warns you because if that variable changes, your hook won't re-run, leading to bugs where your hook uses old ('stale') data.
Plain English Explanation
"Think of the dependency array as an alarm clock. If you tell a robot to bake a cake using eggs, but you don't tell the robot to wake up when the eggs are replaced, the robot will use old, rotten eggs. You must list every ingredient you use in the alarm list."
Code Examples
function Profile({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
// WARNING: userId is used here but not in the array below!
fetchUser(userId).then(setData);
}, []); // <-- Missing dependency
return <div>{data?.name}</div>;
}function Profile({ userId }) {
const [data, setData] = useState(null);
useEffect(() => {
// Fixed: userId is now in the dependency array.
// If the userId prop changes, this effect will re-run automatically.
fetchUser(userId).then(setData);
}, [userId]);
return <div>{data?.name}</div>;
}Step-by-Step Fix
- 1
Look at the variables being used inside the `useEffect`.
- 2
Add any variable that comes from props, state, or context into the dependency array `[]`.
- 3
If you are using a function inside the effect, wrap that function in a `useCallback` hook where it was defined, and add it to the dependency array.
- 4
If you only want the effect to run exactly once (on mount), move the variable or function *outside* of the component so it's not tied to the component's lifecycle.
Prevention Tips
- Always use the `eslint-plugin-react-hooks` package and NEVER disable the `exhaustive-deps` rule.
- If you don't want an effect to re-run, you might be structuring your logic incorrectly. Consider lifting state up.
FAQs & Interview Prep
Why Interviewers Ask About This
Crucial. You will almost certainly be asked how the `useEffect` dependency array works, and what happens if you leave it empty vs omitting it entirely.
Why can't I just use `eslint-disable-next-line`?
Disabling the rule often causes subtle bugs that are incredibly hard to track down, specifically 'stale closures' where your UI shows the wrong data.