React

Error boundary: il pattern che regge

Un error boundary è un componente di classe con getDerivedStateFromError: intercetta gli errori di render del sottoalbero e mostra una via d'uscita.

In sintesi

  • Un error boundary intercetta solo gli errori lanciati durante render e lifecycle: i gestori di eventi restano fuori.
  • Il reset passa da una key sul boundary: cambiarla ricrea il componente e ne azzera lo stato.
  • Un boundary per rotta più uno per i widget esterni copre i casi reali senza moltiplicare i messaggi.

Un error boundary è un componente React che intercetta gli errori lanciati durante il render del suo sottoalbero e mostra un'interfaccia di riserva al posto del componente rotto. Gli errori in un gestore di eventi o in una promessa non passano da lì.

Cosa entra e cosa resta fuori

  • Render e lifecycle: un errore qui sale al boundary più vicino e ferma quel sottoalbero.
  • Gestori di eventi: restano fuori, quindi vanno gestiti con try e catch o con uno stato di errore.
  • Promesse e timer: un catch di una promessa non è un errore di render, e boundary non lo vede.
  • Il boundary stesso: se il fallback lancia, l'errore sale al boundary superiore.

Il componente minimo

import { Component } from "react";

export class ErrorBoundary extends Component {
  state = { rotto: false };

  static getDerivedStateFromError() {
    return { rotto: true };
  }

  componentDidCatch(error, info) {
    console.error(error, info.componentStack);
  }

  render() {
    if (this.state.rotto) {
      return this.props.fallback ?? Qualcosa non ha funzionato.;
    }
    return this.props.children;
  }
}

Due metodi bastano: getDerivedStateFromError cambia lo stato durante il render, componentDidCatch registra l'errore e lo stack dei componenti. Il fallback arriva dalle props, così lo stesso boundary serve più punti.

Reset per chiave, non per fortuna

Un boundary che resta in stato di errore non riprova da solo. La forma che regge mette una key sul boundary legata alla rotta o a un contatore di tentativi: cambiare la key ricrea il componente e con lui lo stato.

Quanti boundary servono

Uno per rotta più uno intorno ai widget esterni. Un solo boundary in cima all'app trasforma un errore locale in pagina bianca; un boundary per ogni card riempie la schermata di messaggi identici.

La categoria error handling raccoglie gli stati di errore del catalogo, con la variante error page; un form di accesso mostra il caso in cui l'errore arriva dalla rete e va scritto a mano.

La limitazione

Il pattern richiede una classe: React non offre un hook equivalente, perché il recupero deve avvenire prima del commit. In sviluppo il boundary non nasconde l'overlay di errore di React, quindi il fallback va provato in build.

Dove continuare

Il file di errore dell'App Router è in error boundary in Next.js; le novità della versione sono in React 19, cosa cambia; gli effect che partono due volte sono in useEffect due volte in sviluppo. Il confronto fra framework è in confronto framework frontend.

Domande frequenti

Un error boundary intercetta gli errori di una fetch?

No. Una promessa rifiutata non è un errore di render: serve un catch che porti il risultato in stato, oppure un boundary alimentato da quello stato.

Perché serve una classe e non un hook?

Perché il recupero deve avvenire prima del commit. Solo i metodi di classe forniscono getDerivedStateFromError, che React chiama durante il render.

Come faccio a riprovare dopo un errore?

Cambiando la key del boundary. La key nuova ricrea il componente e azzera lo stato di errore, quindi il sottoalbero prova un render pulito.

Meglio un boundary per rotta o uno globale?

Uno per rotta è la base, con un boundary globale come rete di sicurezza. Un solo boundary globale trasforma ogni errore locale in pagina bianca.

Il boundary funziona anche sui server component?

No. Un boundary è codice client; nell'App Router il file error.tsx fa lo stesso lavoro per un segmento, con il vantaggio di ricevere l'errore come prop.