Error Boundary è un componente React che intercetta errori JavaScript nel suo albero di componenti figli e visualizza un’interfaccia di fallback invece di una pagina di crash. Nel contesto di React Native, impedisce un arresto anomalo completo dell’applicazione durante errori di rendering non fatali. Secondo la Documentazione React, 2024, error boundary intercetta errori nei metodi render, hook del ciclo di vita e costruttori dei componenti figli, consentendo all’applicazione di continuare a funzionare. In React Native questo è particolarmente critico poiché un’app mobile non può essere ricaricata con F5 — l’utente perde l’intera sessione.
Punti chiave
Error Boundary è un meccanismo React per il degrado graduale durante errori di rendering. Introdotto in React 16 (2017) come componente wrapper che implementa uno dei due metodi del ciclo di vita: static getDerivedStateFromError o componentDidCatch. Error Boundary consente di mostrare all’utente un messaggio significativo invece di una schermata bianca vuota o un arresto anomalo completo dell’applicazione.
Prima di React 16, qualsiasi errore non gestito in render causava un arresto anomalo completo dell’applicazione con smontaggio dell’intero albero DOM. Nelle applicazioni web, questo significava una schermata bianca vuota; in React Native, un arresto anomalo completo con ritorno alla schermata Home. Il team di React ha introdotto Error Boundary come analogo del blocco catch per UI dichiarativa, prendendo in prestito il concetto dall’approccio “let it crash” del linguaggio Erlang.
In React Native, l’assenza di Error Boundary significa un arresto anomalo completo dell’applicazione a qualsiasi errore di rendering. L’utente perde l’intera sessione corrente senza possibilità di recupero. Error Boundary in React Native è criticamente importante perché le app mobili non possono essere ricaricate come le pagine web — la sessione dell’utente viene irrimediabilmente persa e l’utente deve ricominciare da capo.
Error Boundary funziona a livello di albero React. Quando un componente figlio lancia un errore in render o nel ciclo di vita, React non smonta l’intero albero ma passa il controllo all’Error Boundary più vicino nella gerarchia. Il Boundary chiama getDerivedStateFromError, imposta state.hasError = true e renderizza l’interfaccia di fallback invece del ramo di componenti danneggiato.
import React, { Component, ErrorInfo, ReactNode } from "react"
interface Props {
children: ReactNode
fallback?: ReactNode
}
interface State {
hasError: boolean
error?: Error
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error }
}
componentDidCatch(error: Error, info: ErrorInfo) {
console.error("Caught by boundary:", error)
Crashlytics.recordException(error)
}
render() {
if (this.state.hasError) {
return this.props.fallback || <FallbackUI />
}
return this.props.children
}
}
getDerivedStateFromError imposta lo stato per il rendering dell’interfaccia di fallback — è un metodo statico chiamato durante la fase di rendering prima del commit delle modifiche. componentDidCatch viene eseguito nella fase di commit ed è destinato agli effetti collaterali: registrazione, invio di report di crash a Crashlytics, analisi. I due metodi separano la responsabilità tra la gestione dello stato dell’UI e gli effetti collaterali.
Per creare un Error Boundary, è necessario implementare un componente di classe con i metodi getDerivedStateFromError e/o componentDidCatch. I componenti funzionali non possono essere Error Boundary — React supporta questa funzionalità solo per i componenti di classe perché è richiesto l’accesso ai metodi del ciclo di vita. La libreria react-error-boundary fornisce un’implementazione pronta con un’API basata su hook per maggiore comodità.
// Esempio di utilizzo di Error Boundary in React Native
import { ErrorBoundary } from "react-error-boundary"
const FallbackComponent = ({ error, resetError }: FallbackProps) => (
<View style={styles.container}>
<Text>Qualcosa è andato storto</Text>
<Text>{error.message}</Text>
<Button title="Riprova" onPress={resetError} />
</View>
)
const App = () => (
<SafeAreaView>
<ErrorBoundary FallbackComponent={<FallbackComponent />}>
<UserProfile userId={"123"} />
</ErrorBoundary>
<BottomNavigation />
</SafeAreaView>
)
Livelli di incapsulamento — Error Boundary può essere posizionato a diversi livelli della gerarchia. Un Boundary globale alla radice dell’app mostrerà l’interfaccia di fallback a qualsiasi errore, ma la navigazione sarà preservata. Più Boundaries a livello di schermo consentono di isolare gli errori: se uno schermo si rompe, gli altri continuano a funzionare indipendentemente. react-error-boundary semplifica il meccanismo di reset attraverso l’hook useErrorBoundary, consentendo di reimpostare lo stato senza ricaricare. Per progetti tipici, uno schema a tre livelli di Boundary è considerato ottimale per applicazioni React Native.
Dopo un errore, l’utente può fare clic sul pulsante “Riprova”, che reimposta hasError su false e ri-renderizza l’albero figlio. Il meccanismo di reset è importante per ripristinare la funzionalità dell’applicazione senza ricaricare. In react-error-boundary, viene utilizzato il callback onReset, che può cancellare la cache, richiedere nuovamente i dati o aggiornare lo stato più in alto nell’albero.
Error Boundary non intercetta errori asincroni — errori in setTimeout, setInterval, Promise, async/await. React non può intercettare errori al di fuori del ciclo di rendering e degli hook del ciclo di vita perché vengono eseguiti in contesti di esecuzione diversi. Per errori asincroni, è necessario un try-catch separato nei gestori o un gestore globale di eventi unhandledrejection.
Gli errori in onClick, onChange e altri gestori di eventi non vengono intercettati da Error Boundary perché vengono eseguiti al di fuori del rendering React. La gestione degli errori per i gestori di eventi deve essere all’interno del gestore stesso usando try-catch. La libreria react-error-boundary fornisce l’hook useErrorHandler per lanciare errori dai gestori di eventi al Boundary più vicino.
Error Boundary non funziona sul lato server in Next.js o Gatsby. I metodi getDerivedStateFromError e componentDidCatch non vengono chiamati durante SSR perché i metodi del ciclo di vita sono disponibili solo nel browser. Per errori del server, è necessaria una strategia separata: try-catch in getServerSideProps, pagine di fallback error.js (Next.js 13+), o middleware globale.
In React Native, Error Boundary non previene arresti anomali a livello di moduli nativi. Un arresto anomalo nativo (segfault, esaurimento memoria, eccezione nativa) si verifica a livello Objective-C o Java e non raggiunge il livello JavaScript. Per arresti anomali nativi, sono necessari Crashlytics NDK (Android) o KSCrash (iOS). Error Boundary protegge solo il livello JavaScript di un’applicazione React Native.
Posiziona Error Boundary ai confini dei moduli logici: un Boundary per schermo, uno per widget di terze parti, uno per modulo complesso. Questo isola gli errori e consente all’utente di continuare a lavorare in altre parti dell’applicazione. Un Boundary radice dovrebbe essere sempre presente — per errori critici in componenti di navigazione comuni o provider. Ogni Boundary è responsabile del proprio frammento di interfaccia e non influisce sui componenti vicini quando si verifica un errore.
Passa sempre l’errore a Crashlytics o Sentry tramite componentDidCatch. Aggiungi contesto: nome dello schermo, userId, versione dell’app, parametri di navigazione. In Sentry, sono disponibili breadcrumb — una sequenza di azioni dell’utente che hanno portato all’errore. Per analizzare la frequenza degli errori non fatali, utilizza i dashboard di Crashlytics con raggruppamento per issue.
Non utilizzare un fallback nudo — crea un’interfaccia significativa. Set consigliato per React Native: messaggio di errore (user-friendly, non tecnico), un pulsante “Riprova”, un link al supporto o chat. Evita una View vuota — l’utente penserà che l’app si sia completamente bloccata e la chiuderà. Il fallback dovrebbe essere integrato nel design complessivo dell’app.
Testa ogni Error Boundary usando React Testing Library o React Native Testing Library. Crea un componente trigger che lancia un errore durante il rendering e verifica che l’interfaccia di fallback venga visualizzata. Per i test di integrazione, usa storybook con diversi stati di Error Boundary: normale, errore, stato post-reset. Il test automatizzato di Boundary garantisce che quando il componente cambia, l’interfaccia di fallback continui a funzionare correttamente in produzione. La copertura dei test per ogni Boundary dovrebbe essere un requisito obbligatorio di code review per progetti React Native.
Domande frequenti
React implementa Error Boundary solo attraverso componenti di classe perché è richiesto l’accesso ai metodi del ciclo di vita componentDidCatch e getDerivedStateFromError. I componenti funzionali non hanno tali metodi. La libreria react-error-boundary fornisce un wrapper di classe pronto con un’API basata su hook per facilità d’uso.
L’impatto è minimo — Error Boundary aggiunge un controllo di stato ad ogni rendering dell’albero figlio. Il confronto di state.hasError è un’operazione O(1) con complessità costante. Quando non ci sono errori, non c’è overhead. Solo quando si verifica un errore, il Boundary esegue un rendering aggiuntivo dell’interfaccia di fallback.
No, 2–3 livelli sono sufficienti: un Boundary radice per l’intera applicazione, un Boundary di schermo per ogni ramo di navigazione e un Boundary locale per widget critici (modulo di pagamento, mappa, chat). L’uso eccessivo di Boundaries complica l’architettura senza un significativo beneficio.
Error Boundary e Suspense sono indipendenti: Suspense intercetta il caricamento (Promise in sospeso in React 18+), Error Boundary intercetta errori di rendering. Possono essere combinati: <ErrorBoundary><Suspense><Component /></Suspense></ErrorBoundary>. Suspense si attiva prima durante il caricamento, Error Boundary si attiva in caso di errore del componente caricato.
try-catch intercetta errori in codice imperativo sincrono ma non può intercettare errori di rendering JSX. Error Boundary è specificamente progettato per UI dichiarativa: intercetta errori in render, hook del ciclo di vita e costruttori di componenti figli, cosa che try-catch non può fare a causa delle specificità del rendering React.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche