StrictMode
StrictMode surfaces potential problems in your components during development.
<StrictMode> is a development-only wrapper that helps you catch bugs early. It does not render any visible UI and has no effect in production builds.
What it does
- Double-invokes component bodies and certain functions to detect impure code.
- Re-runs effects once extra on mount to reveal missing cleanup.
- Warns about deprecated APIs.
If your component behaves oddly in development but you see the code run twice, that is StrictMode helping — write pure components and proper effect cleanup and it will be fine.
Example
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
);When to use it
- A development team wraps their app in StrictMode during code review sprints to catch components that rely on side-effects during rendering before they reach production.
- A React upgrade project uses StrictMode to detect deprecated lifecycle methods and legacy string refs that need migrating to the current API.
- An open-source library enables StrictMode in its test suite to verify all components survive double-invocation without producing different output.
More examples
Wrap full app in StrictMode
Applies StrictMode to the entire application so every component is double-checked during development.
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
);StrictMode on one subtree
Scopes StrictMode to a single legacy subtree so only that section receives the additional checks.
import { StrictMode } from 'react';
import LegacyWidget from './LegacyWidget';
function App() {
return (
<div>
<Header />
<StrictMode>
<LegacyWidget />
</StrictMode>
<Footer />
</div>
);
}Impure render StrictMode exposes
Contrasts an impure render that StrictMode's double-invocation will expose with the corrected version.
// BAD — mutates module-level variable during render
let callCount = 0;
function BadCounter() {
callCount += 1; // StrictMode double-calls this, so count jumps by 2
return <p>Called {callCount} times</p>;
}
// GOOD — local state, pure render
function GoodCounter() {
const [count, setCount] = React.useState(0);
React.useEffect(() => setCount(c => c + 1), []);
return <p>Count: {count}</p>;
}
Discussion