React

StrictMode: perché gli effect partono due volte

In sviluppo StrictMode monta, smonta e rimonta ogni componente per verificare il cleanup: se l'effect parte due volte, manca una pulizia.

In sintesi

  • StrictMode raddoppia solo in sviluppo il montaggio, per far emergere cleanup mancanti.
  • In produzione l'effect di mount gira una volta sola: il doppio non è un bug.
  • Un effect con fetch ha bisogno di un AbortController, o la risposta arriva due volte.

StrictMode raddoppia il montaggio degli effect solo in sviluppo, per costringere ogni effect a smontarsi bene: se il secondo giro rompe qualcosa, il cleanup manca.

Cosa fa esattamente

React 19 monta il componente, esegue l'effect, lo smonta eseguendo la funzione di cleanup e lo rimonta. Nessuna riga del tuo codice è cambiata: il doppio giro è una prova, non una modifica al comportamento atteso. In produzione il ciclo avviene una volta.

L'effect che regge la prova

useEffect(() => {
  const controller = new AbortController();
  fetch("/api/projects", { signal: controller.signal })
    .then((response) => response.json())
    .then(setProjects)
    .catch((error) => {
      if (error.name !== "AbortError") console.error(error);
    });
  return () => controller.abort();
}, []);

Al primo smontaggio abort() annulla la richiesta in volo; il secondo montaggio ne avvia una nuova. Senza cleanup la prima risposta scriverebbe sullo stato di un componente già smontato.

I sintomi tipici

  • Due richieste: il doppio POST in sviluppo è il segnale più frequente di un effect senza guardia.
  • Listener duplicati: addEventListener senza removeEventListener accumula handler a ogni montaggio.
  • Timer doppi: un setInterval senza clearInterval raddoppia la frequenza dopo il rimontaggio.

Un progetto per provarlo

npm run build
npm run preview

La build di produzione non contiene il doppio montaggio: se il problema sparisce con npm run preview e resta con npm run dev, hai trovato un cleanup mancante.

Tre componenti che leggono una preferenza in un effect al montaggio: theme-toggle, auth-switch e sky-toggle. Per esplorare per categoria parti da 111.985 componenti.

La limitazione

StrictMode verifica che il cleanup esista, non che l'effect sia corretto: un effect con dipendenze sbagliate resta sbagliato anche con il doppio montaggio, e nessun avviso lo segnala. Non sostituisce i test, e in sviluppo può raddoppiare chiamate a servizi esterni che non si possono annullare.

Dove continuare

Cosa cambia in React 19 è in React 19; il confine fra componenti server e hook è in server component e hook; il confronto fra ecosistemi è in Vue 3 vs React.

Domande frequenti

Il doppio effect è un bug di React?

No, è una prova voluta e solo in sviluppo. Serve a far emergere effect senza cleanup, che in produzione causerebbero doppie richieste.

Posso disattivare StrictMode?

Sì, togliendo il wrapper, ma perdi il controllo sui cleanup. Meglio correggere gli effect: la produzione non cambia.

Perché la richiesta parte due volte in sviluppo?

Perché il primo montaggio viene smontato subito e la richiesta non è annullata. Aggiungi un AbortController e il primo giro si ferma.

StrictMode controlla anche i render?

Sì, in sviluppo esegue due volte il corpo del componente e i reducer, per rendere visibili gli effetti collaterali durante il render.

StrictMode vale anche con i Server Component?

No. Il doppio montaggio riguarda il client; i Server Component vengono eseguiti dal server e non hanno effect.