React · Frontend system thinking

How do you think about useEffect dependencies?

MediumuseEffectdependenciesreactive valuesUpdated Oct 2026
Quiz this track

Short answer

Include every reactive value the effect reads: props, state and values derived from them. React compares dependencies with Object.is and re-runs the effect when one changes.

The dependency array is not a scheduling hint. It is the list of inputs the effect depends on. If the effect reads a value from the component scope and that value can change between renders, it belongs in the array. Omitting it lets the effect close over an old render's value.

jsx
function Room({ roomId, serverUrl }) {
  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();

    return () => connection.disconnect();
  }, [roomId, serverUrl]);
}
The effect reads roomId and serverUrl, so both are dependencies. When either changes, it disconnects and reconnects.

What counts as reactive

  • Props and state
  • Values computed from props or state during render
  • Functions declared in the component that close over reactive values
  • Context values read with useContext

Objects, arrays and functions get a new identity on every render. If an effect depends on one, it may re-run more often than expected. Move stable values outside the component, memoize them when appropriate, or restructure the effect so it depends on primitive inputs instead of a freshly created object.

jsx
function Search({ query }) {
  useEffect(() => {
    const id = setTimeout(() => {
      searchApi(query);
    }, 300);

    return () => clearTimeout(id);
  }, [query]);

  return <input value={query} readOnly />;
}
The cleanup cancels the previous timer, so only the latest query is sent.
Do not disable the exhaustive-deps lint rule to hide a dependency you do not want. Either add the dependency and make the effect safe to re-run, or remove the reactive read from the effect.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What is the difference between an empty array and omitting the array?
  2. 2Why does an effect with an object dependency run on every render?
  3. 3Are functions stable between renders?
  4. 4How do you handle an effect that should read the latest value without re-subscribing?

Say it in the interview

I treat the dependency array as the effect's inputs. Anything reactive that the effect reads, including props, state, derived values and context, goes in the array. React compares entries with Object.is, so a new object or function identity can cause extra runs. If a dependency makes the effect run too often, I fix the effect or stabilise the value rather than suppressing the lint warning.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live React mock interview and get scored feedback on depth, clarity and confidence.