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.
Why StrictMode re-runs useEffect: what interviewers expect
Interview quick answer
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
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: 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
// 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 |
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 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.
// 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.
Use this as one explanation rep, then continue with the React interview questions cluster or a guided prep path.