Strict Mode

<StrictMode> turns on extra checks for everything below it, in development builds only; it has no effect on a production build. Vite 25,978 's React 7,897 template wraps the whole app in it and there is rarely a reason to take it out — but the first time you meet it, its behavior looks like a bug, so it is worth seeing directly.

Strict Mode double-invoking render and effect setupHTMLLive
<div id="root"></div><style>body{font:14px system-ui;margin:6px}</style>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone@8.0.5/babel.min.js"></script>
<script type="importmap">{ "imports": { "react": "https://esm.sh/react@19.3.0?dev",
  "react-dom/client": "https://esm.sh/react-dom@19.3.0/client?dev" } }</script>
<script type="text/babel" data-type="module">
  import React, { StrictMode, useState, useEffect } from 'react';
  import { createRoot } from 'react-dom/client';
  let renders = 0, setups = 0, cleanups = 0;
  function Probe() {
    renders++;                                    // impure on purpose, to be counted
    const [, setTick] = useState(0);
    useEffect(() => {
      setups++;
      const id = setTimeout(() => setTick(1), 80);
      return () => { cleanups++; clearTimeout(id); };
    }, []);
    return <p>render calls: {renders} — effect setups: {setups} — cleanups: {cleanups}</p>;
  }
  createRoot(document.getElementById('root')).render(
    <StrictMode><Probe /></StrictMode>);
</script>
Browser output of Listing 2.94
Browser output of 94

Mounting once produced two render calls and a setup-cleanup-setup cycle; the state update 80 ms later rendered twice more, giving the four calls and two setups on screen. React runs your code twice on purpose to see whether it behaves the same both times. The double render catches impure rendering — renders++ is exactly the mutation it hunts for — and the extra setup/cleanup cycle catches effects that subscribe without unsubscribing, which in production would leak on every remount. Callback refs get the same attach-detach-attach treatment, as do the functions passed to useState, useMemo and useReducer. Strict Mode also warns about deprecated APIs reached through old dependencies: unsafe legacy lifecycles, and the patterns React 19 removed outright.