Why does my useEffect run twice in development?
In Strict Mode, React 18 and later deliberately mounts, unmounts and remounts each component once in development to check that effects clean up properly. It does not happen in production.
Explain it simply
A shopkeeper tests the shutter by pulling it down and up once before opening. React Strict Mode does the same: mount, run cleanup, mount again. If your effect survives that, it will also survive a real user navigating away and back.
If you see a double network call or a doubled subscription, the effect is missing its cleanup, not React misbehaving.
Example
useEffect(() => {
const ws = new WebSocket(url);
return () => ws.close(); // needed: the first connection is closed in dev
}, [url]);For one-time work that must not repeat (like analytics on page view), make it safe to run twice, or trigger it from an event rather than an effect.
What to say in the interview
"Strict Mode intentionally re-runs effects once in development to surface missing cleanup. Production runs them once. The fix is a proper cleanup function, not removing StrictMode or adding a ref hack to skip the second run."
Common mistakes
- Disabling StrictMode to hide the double call.