Strict Mode
Overview
If you have ever written a useEffect with an empty dependency array [] (which is supposed to run only once), but noticed it inexplicably console.logs TWICE when your app loads, you are experiencing React Strict Mode.
Strict Mode is a developer tool built directly into React to help you write resilient, future-proof code. When enabled, it intentionally double-invokes certain lifecycle methods and, most notably, mounts, unmounts, and remounts your components in quick succession on the very first load.
React does this on purpose to actively hunt down hidden bugs in your code. Specifically, it tests whether your useEffect Cleanup Functions are actually working. If you forget to clear a timer in your cleanup, the double-mount will result in two active timers running, instantly alerting you to the memory leak before you ship the code to production.
Note: Strict Mode ONLY runs in development (localhost). It is completely disabled in production builds.
Syntax
// main.jsx (The entry point of a Vite/React App)
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
ReactDOM.createRoot(document.getElementById('root')).render(
// Wrapping the entire app activates the extra checks
<React.StrictMode>
<App />
</React.StrictMode>,
)Common Pitfalls
- Removing Strict Mode to 'fix' double logs: Many beginners get annoyed by the double
console.logand delete the<React.StrictMode>tag to 'fix' it. This is a terrible idea. You are essentially turning off your smoke alarms because the beeping is annoying. The double render is simulating exactly what will happen when users rapidly navigate back and forth in your app.
Interview Questions
In development mode, React Strict Mode intentionally runs the mount -> unmount -> mount cycle to stress-test your components. It verifies that your components are pure and that your useEffect cleanup functions are correctly implemented and free of memory leaks.
No. Strict Mode is purely a development-time tool. When you run npm run build and deploy the application, Strict Mode is completely bypassed and components will only mount once.
Real-World Example
Strict Mode catching a WebSocket bug: Strict mode simulates a user clicking 'Join Chat', immediately clicking 'Back', and then 'Join Chat' again. If your cleanup function is missing or broken, this rapid navigation will catastrophically break your app. Strict mode forces you to fix it immediately.
function ChatRoom() {
useEffect(() => {
// 1. Mount 1: Connects
// 3. Mount 2: Connects AGAIN!
const socket = new WebSocket('ws://chat.server');
socket.onmessage = (msg) => console.log(msg);
// If you FORGET this cleanup function...
// Strict mode's double-mount will cause you to have TWO active socket connections!
// You'll see every chat message printed twice in the console, instantly revealing the bug.
return () => {
// 2. Unmount 1: Strict mode forces this to run, gracefully closing the first socket
socket.close();
};
}, []);
return <div>Chat UI</div>;
}Check Your Knowledge
Test your understanding of Strict Mode with these quick questions.