React · Frontend system thinking

Why does useEffect return a cleanup function?

MediumuseEffectcleanupsubscriptionsUpdated Oct 2026
Quiz this track

Short answer

Cleanup undoes an effect's setup before it runs again or when the component unmounts. It prevents duplicate subscriptions, leaked timers and updates from stale work.

Effects describe a synchronization process. Setup starts it and cleanup stops it. React calls cleanup before re-running the effect with new dependencies and once when the component unmounts. Without cleanup, every re-run can add another listener, timer or connection.

jsx
function Timer({ intervalMs }) {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setSeconds((current) => current + 1);
    }, intervalMs);

    return () => clearInterval(id);
  }, [intervalMs]);

  return <p>{seconds} seconds</p>;
}
When intervalMs changes, the old interval is cleared before a new one starts.

What cleanup is for

  • Removing event listeners and unsubscribing from stores
  • Clearing timers and animation frames
  • Aborting requests or ignoring their late results
  • Disconnecting sockets and releasing third-party instances
jsx
useEffect(() => {
  let ignore = false;

  async function load() {
    const result = await fetchProfile(userId);
    if (!ignore) {
      setProfile(result);
    }
  }

  load();

  return () => {
    ignore = true;
  };
}, [userId]);
The flag prevents an older request from overwriting the profile when userId changes quickly.

Cleanup is about correctness, not only memory. A late response or a duplicated listener can make the UI show the wrong state even if nothing leaks. The effect should be written so that setup, cleanup and another setup leaves the same result as a single setup.

An effect's cleanup cannot be async. If teardown needs asynchronous work, start it without awaiting inside the cleanup and handle errors explicitly.

Follow-ups you should expect

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

  1. 1When exactly does React run effect cleanup?
  2. 2How do you cancel a fetch when dependencies change?
  3. 3Why does StrictMode mount, unmount and remount effects in development?
  4. 4What happens if cleanup removes a listener that was never added?

Say it in the interview

Cleanup is the teardown half of an effect. React runs it before the effect runs again and when the component unmounts. I use it to remove listeners, clear timers, disconnect sockets and invalidate in-flight requests. The goal is for setup and cleanup to be symmetrical, so repeated runs do not duplicate subscriptions or apply stale results.

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.