React StrictMode Explained: What It Does in Development

StrictMode runs extra development-only checks that reveal impure rendering and missing Effect cleanup. Learn what it does and why it stays out of production.

5 min read

React StrictMode is a development-only wrapper that makes React run extra checks on the components inside it. Those checks double some rendering and Effects work in development, so bugs such as impure components and missing cleanup become visible early. It is the safety net you get for free with a fresh Vite template, and StrictMode changes nothing in production.

Enable StrictMode

Wrap your root component in StrictMode when you render it. If a tool such as Vite generated your project, the default main.jsx file usually includes this already.

App.jsxApp.jsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
 
const root = createRoot(document.getElementById("root"));
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

The wrapper accepts no props and changes nothing about what renders. In development it adds the checks; in production it is removed.

StrictMode comes from the react package, so there is nothing extra to install. You can also wrap only part of the app, and the checks apply to that subtree.

Double rendering finds impure components

StrictMode calls your component function bodies twice in development. A pure component returns the same JSX both times, so the extra call changes nothing.

An impure component mutates props or outside variables, and the double call makes that mutation visible:

App.jsxApp.jsx
function StoryTray({ stories }) {
  stories.push({ id: "create", label: "Create Story" });
  return <ul>{stories.map((s) => <li key={s.id}>{s.label}</li>)}</ul>;
}

This component pushes into the stories array it received as a prop. Under StrictMode it runs twice, so "Create Story" appears twice and the mistake shows up immediately.

The fix is to copy the array before modifying it. Event handlers are not doubled, so a click handler still runs once.

Effects run an extra setup and cleanup

StrictMode also runs one extra setup and cleanup cycle for every Effect in development. An Effect that connects to a server without cleanup leaves two connections instead of one.

The setup, cleanup, setup pattern is a signal to add cleanup. The extra cycle runs on mount, so a connection appears, disconnects, and connects again when cleanup is missing. For the details of Effect cleanup, see the guide on React useEffect.

The other checks

StrictMode also re-runs ref callbacks once in development and warns about deprecated class lifecycle methods. Both follow the same idea: surface a cleanup or migration problem early, before it reaches your users. You rarely need to touch these in a new app, but the warnings keep older code honest.

All of these checks disappear from the production build, so they do not slow down the app your users run. The double work is a development signal, not a production behavior, which is why the guide on render and commit phases is worth reading next.

Rune AI

Rune AI

Key Insights

  • StrictMode runs checks only in development.
  • It double-calls component function bodies to find impure rendering.
  • It re-runs Effects to reveal missing cleanup.
  • It re-runs ref callbacks and flags deprecated APIs.
  • Production builds strip all of these checks.
RunePowered by Rune AI

Frequently Asked Questions

Does StrictMode run in production?

No. All StrictMode checks are development-only. They add no work to the production build your users receive.

Why does my component render twice in development?

StrictMode double-calls component function bodies to surface impure rendering. A pure component returns the same result both times, so the extra call changes nothing.

Why do my Effects run twice in development?

StrictMode runs one extra setup and cleanup cycle per Effect. It reveals missing cleanup logic, which would otherwise cause leaks only after users interact with the app.

Conclusion

StrictMode is a development-only wrapper that double-checks your components. It re-runs render functions, Effects, and ref callbacks to expose impure code and missing cleanup before those bugs reach production. Nothing it does carries into the production build.