Explain useEffect dependency array behavior for [], [deps], and omitted
![Explain useEffect dependency array behavior for [], [deps], and omitted](/_next/image?url=https%3A%2F%2Freact.dev%2Fimages%2Fog-reference.png&w=1600&q=75)
It tests reactive dependency tracking. Omitting re-runs every render; [] runs on mount with cleanup on unmount; [deps] re-runs when Object.is detects change. Red flag: claiming [] means 'run once' without mentioning cleanup or stale values.
WHAT THIS TESTS: This question checks if you know how React decides when to run an Effect, not just the API syntax. The interviewer wants to see that you think in terms of reactive dependencies and commit phases, not just memorized rules. They are listening for whether you treat Effects as synchronization with an external system rather than lifecycle methods.
A GOOD ANSWER COVERS: First, omitting the dependency array entirely means React has no snapshot to compare against, so the Effect runs after every single render commit. Second, passing an empty array [] tells React to compare against a stable empty snapshot, so the setup function runs only after the initial mount; the cleanup function runs when the component unmounts, and in Strict Mode the setup-cleanup cycle may execute twice to help detect side effects. Third, passing a populated array like [serverUrl, roomId] means React performs an Object.is comparison between the current and previous render values for each dependency; if any value changed, React first runs the cleanup from the previous render with old values, then runs the setup with new values. Fourth, you should mention that the dependency list must be written inline, have a constant number of items, and include every reactive value read inside the setup code.
COMMON WRONG ANSWERS: A major red flag is saying that [] means the Effect runs exactly once and nothing else happens. This ignores cleanup, ignores that the Effect may re-run in development under Strict Mode, and invites stale closure bugs if you read reactive values that were omitted from the array. Another red flag is claiming that omitting the array is the same as passing []; it is not, because no array means no dependency check at all. A third red flag is failing to mention Object.is comparison or describing the check as deep equality; React uses Object.is, which is shallow and reference-based for objects and functions.
LIKELY FOLLOW-UPS: The interviewer may ask how you would handle a function or object dependency that changes on every render without being semantically different. They might ask why the React linter enforces exhaustive-deps and what happens if you lie to it. They could also ask when you would use useLayoutEffect instead, or how to refactor an Effect that fetches data based on props.
ONE CONCRETE EXAMPLE: Imagine a ChatRoom component with props roomId and state serverUrl. If you write useEffect with [roomId], the Effect re-connects to a new chat room whenever roomId changes, but it reads a stale serverUrl if serverUrl is not in the array. If you write useEffect with [], it connects once on mount using the initial roomId and serverUrl, never updates when the user switches rooms, and disconnects on unmount. If you omit the array entirely, it disconnects and reconnects after every keystroke or state update, which is usually wasteful and can cause performance problems or dropped connections.
Source: react.dev
Read the original → react.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.