Why StrictMode re-runs useEffect: what interviewers expect

HighIntermediateReact

Interview quick answer

Use this React StrictMode interview answer to explain why effects re-run in development, why event handlers stay single, and how cleanup prevents duplicate fetches or listeners.

Interview focus

This React interview question tests whether you can explain the StrictMode signal without overreacting: dev-only effect re-runs, event handlers staying single, and cleanup preventing duplicate work.

  • Explain why StrictMode re-runs effect setup and cleanup in development only
  • Clarify that event handlers are not double-invoked by the render check
  • Show how cleanup, aborting requests, or deduping ownership stops duplicate work
Practice more React interview questions
Interview answer drill

Use this React interview question to rehearse a quick answer, common mistake, follow-up, and production pitfall.

Full interview answer

60-second interview answer

React useEffect running twice in StrictMode during development, not production, is intentional. The answer interviewers expect is simple: StrictMode re-runs effects in development, event handlers still run from user actions, and cleanup prevents duplicate fetches or listeners. React runs an extra setup and cleanup cycle to expose missing cleanup and unsafe side effects. Event handlers are not double-invoked by this render check. If the second run creates duplicate fetches, listeners, subscriptions, timers, or analytics events, the effect likely owns that work incorrectly.

Production pitfall: dev-only signal

No. StrictMode checks are development-only. They do not change the production build, but they reveal bugs that can still happen in production through route changes, remounts, aborted work, stale requests, or missing unsubscribe logic.

Mental model interviewers expect

React is asking: "If I set up this effect, clean it up, and set it up again, does anything leak or duplicate?" A correct effect treats cleanup as part of the contract, not as optional polish.

Surface

StrictMode behavior

What it catches

Component function body

Can run an extra time in development

Impure render logic, prop mutation, global mutation

Effect setup and cleanup

Runs setup, cleanup, then setup again in development

Missing cleanup, duplicate listeners, duplicate requests

Ref callbacks

Can re-run in development

Missing ref cleanup

Event handlers

Not double-invoked by the render check

Click or submit work should stay in the event path

Production build

No extra StrictMode diagnostic cycle

Production behavior is not duplicated by StrictMode

Common follow-up: what runs twice

Common follow-up: root vs subtree StrictMode

When StrictMode wraps the root, React can run the initial extra effect setup and cleanup cycle. When StrictMode only wraps a subtree, React only enables checks that can happen in production; it does not create an impossible parent/child effect ordering just to double-fire child effects.

Common follow-up: event handlers

No. StrictMode event handlers are not double-invoked by the render check. StrictMode can double-call render-phase logic that should be pure, but it does not call your click, submit, or keyboard handlers twice as part of that check. If a side effect belongs to a user action, keep it in the event handler instead of moving it into an effect just to run after render.

Production pitfall: missing cleanup

JSX
// Bad: the listener survives the first dev setup cycle
useEffect(() => {
  window.addEventListener('resize', onResize);
}, []);

// Good: cleanup makes setup -> cleanup -> setup safe
useEffect(() => {
  window.addEventListener('resize', onResize);
  return () => window.removeEventListener('resize', onResize);
}, []);
                  

Symptom

Likely root cause

Fix

Duplicate resize, socket, or store callbacks

Effect subscribes but never unsubscribes

Return cleanup that removes the listener or subscription

Duplicate fetches in development

Request starts in an effect without abort or stale-result handling

Use AbortController, ignore stale results, or move fetching to the route/data layer

Duplicate analytics pageviews

Permanent tracking work is owned by component mount

Move tracking to a router boundary, make it idempotent, or dedupe in analytics

Render changes data twice

Component body mutates props or external state

Keep render pure; clone before changing data

Production fixes interviewers expect

Production pitfall: duplicate fetches

If a fetch or API call starts inside an effect, React StrictMode may start it during the first development setup cycle, clean up, and then start it again. That is why searches like useEffect fetch called twice StrictMode and React StrictMode duplicate API calls usually point back to request ownership. Abort the old request, ignore stale results, or move fetching to a route/data layer when component mount is not the right owner.

JSX
// Cleanup-safe request ownership
useEffect(() => {
  const controller = new AbortController();

  fetch(`/api/profile/${userId}`, { signal: controller.signal })
    .then((response) => response.json())
    .then((profile) => {
      if (!controller.signal.aborted) setProfile(profile);
    })
    .catch((error) => {
      if (controller.signal.aborted) return;
      setError(error);
    });

  return () => controller.abort();
}, [userId]);
                  

Common follow-up: should you disable StrictMode?

Usually no. Disabling StrictMode hides the signal instead of fixing the ownership bug. It can be acceptable as a temporary migration step around legacy code, but the durable fix is to make effects cleanup-safe, idempotent, and owned by the right component or route boundary.

Common follow-up: what about Next.js?

Next.js apps commonly enable React StrictMode during development, so Next.js useEffect runs twice usually has the same root cause: the effect is being stress-tested, not duplicated in production. Do not make this a Next.js-only diagnosis unless the bug depends on routing, server/client boundaries, or framework data fetching.

60-second interview framing

Say it like this:
"In development, React StrictMode can run an extra effect setup and cleanup cycle. That is why useEffect may appear to run twice. It is not a production duplicate; it is a diagnostic that exposes missing cleanup, unsafe subscriptions, stale requests, and side effects that should be idempotent or owned somewhere else."

Summary

useEffect can run twice in React StrictMode because development StrictMode intentionally re-runs effect setup and cleanup to reveal bugs. Event handlers are not double-invoked by this check, and production does not run the extra cycle. Fix the underlying effect by adding cleanup, aborting stale requests, deduping permanent side effects, or moving user-triggered work into event handlers.

Similar questions
Guides
Preparing for interviews?