Error Boundary este o componentă React care interceptează erorile JavaScript în arborele său de componente copil și afișează o interfață de rezervă în locul unei pagini de crash. În contextul React Native, previne blocarea completă a aplicației la erori nefatale de randare. Conform React Documentation, 2024, error boundary captează erorile în metodele render, lifecycle-hookuri și constructorii componentelor copil, permițând aplicației să continue funcționarea. În React Native acest lucru este deosebit de critic, deoarece aplicația mobilă nu se reîncarcă cu F5 — utilizatorul pierde întreaga sesiune.
Principalele puncte
Error Boundary este un mecanism React pentru degradare grațioasă la erorile de randare. Introdus în React 16 (2017) ca o componentă-wrapper care implementează una dintre cele două metode de ciclu de viață: static getDerivedStateFromError sau componentDidCatch. Error Boundary permite afișarea unui mesaj inteligibil utilizatorului în locul unui ecran alb gol sau al unui crash complet al aplicației.
Înainte de React 16, orice eroare negestionată în render ducea la crashul întregii aplicații cu demontarea întregului arbore DOM. În aplicațiile web însemna un ecran alb gol, în React Native — crashul complet al aplicației cu revenirea la Home Screen. Echipa React a introdus Error Boundary ca echivalent al blocului catch pentru UI declarativ, împrumutând conceptul din abordarea „lasa-l să se prăbușească” din limbajul Erlang.
În React Native, absența Error Boundary înseamnă crashul complet al aplicației la orice eroare de randare. Utilizatorul pierde întreaga sesiune curentă fără posibilitatea de recuperare. Error Boundary în React Native este critic, deoarece aplicațiile mobile nu se reîncarcă precum paginile web — sesiunea utilizatorului este pierdută ireversibil, iar utilizatorul trebuie să înceapă totul de la capăt.
Error Boundary funcționează la nivelul arborelui React. Când o componentă copil aruncă o eroare în render sau lifecycle, React nu demontează întregul arbore, ci transferă controlul celui mai apropiat Error Boundary mai sus în ierarhie. Boundary apelează getDerivedStateFromError, setează state.hasError = true și renderuiește fallback UI în locul ramurii defecte de componente.
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("Capturat de boundary:", error)
Crashlytics.recordException(error)
}
render() {
if (this.state.hasError) {
return this.props.fallback || <FallbackUI />
}
return this.props.children
}
}
getDerivedStateFromError setează starea pentru randarea fallback UI — aceasta este o metodă statică apelată în faza de randare înainte de confirmarea modificărilor. componentDidCatch se execută în faza de confirmare și este destinat efectelor secundare: logare, trimiterea crash-reporturilor către Crashlytics, analitică. Cele două metode împart responsabilitatea între gestionarea stării UI și acțiunile secundare.
Pentru a crea Error Boundary, trebuie implementată o componentă de clasă cu metodele getDerivedStateFromError și/sau componentDidCatch. Componentele funcționale nu pot fi Error Boundary — React suportă această funcționalitate doar pentru componentele de clasă, deoarece este necesar accesul la metodele de ciclu de viață. Biblioteca react-error-boundary oferă o implementare gata făcută cu API de hookuri pentru comoditate.
// Exemplu de utilizare Error Boundary în React Native
import { ErrorBoundary } from "react-error-boundary"
const FallbackComponent = ({ error, resetError }: FallbackProps) => (
<View style={styles.container}>
<Text>Ceva nu a funcționat</Text>
<Text>{error.message}</Text>
<Button title="Reîncearcă" onPress={resetError} />
</View>
)
const App = () => (
<SafeAreaView>
<ErrorBoundary FallbackComponent={<FallbackComponent />}>
<UserProfile userId={"123"} />
</ErrorBoundary>
<BottomNavigation />
</SafeAreaView>
)
Niveluri de înfășurare — Error Boundary poate fi plasat la diferite niveluri ale ierarhiei. Un Boundary global la rădăcina aplicației va afișa fallback UI la orice eroare, dar navigația va funcționa în continuare. Mai multe Boundary la nivel de ecrane permit izolarea erorilor: dacă un ecran s-a defectat, celelalte continuă să funcționeze independent. react-error-boundary simplifică mecanismul Reset prin hookul useErrorBoundary, permițând resetarea stării fără reîncărcare. Pentru proiectele tipice, schema cu trei niveluri de Boundary este considerată optimă pentru aplicațiile React Native.
După apariția erorii, utilizatorul poate apăsa butonul „Reîncearcă”, care resetează hasError la false și rerandarează arborele copil. Mecanismul Reset este important pentru restabilirea funcționalității aplicației fără reîncărcare. În react-error-boundary se folosește callbackul onReset, care poate goli cache-ul, re-solicita date sau actualiza starea mai sus în arbore.
Error Boundary nu captează erorile asincrone — erorile în setTimeout, setInterval, Promise, async/await. React nu poate intercepta erorile în afara ciclului de randare și a lifecycle-hookurilor, deoarece acestea se execută în alte contexte de execuție. Pentru erorile asincrone este necesar un try-catch separat în handleri sau un handler global al evenimentului unhandledrejection.
Erorile în onClick, onChange și alți event-handleri nu sunt captate de Error Boundary, deoarece se execută în afara randării React. Gestionarea erorilor pentru event-handleri trebuie să fie în interiorul handlerului însuși prin try-catch. Biblioteca react-error-boundary oferă hookul useErrorHandler pentru transmiterea erorilor din event-handleri către cel mai apropiat Boundary.
Error Boundary nu funcționează pe partea de server în Next.js sau Gatsby. Metodele getDerivedStateFromError și componentDidCatch nu sunt apelate la SSR, deoarece metodele de ciclu de viață sunt disponibile doar în browser. Pentru erorile de server este necesară o strategie separată: try-catch în getServerSideProps, pagini fallback error.js (Next.js 13+) sau middleware global.
În React Native, Error Boundary nu previne crashul la nivelul modulelor native. Crashul nativ (segfault, out-of-memory, excepție nativă) are loc la nivelul Objective-C sau Java și nu ajunge la stratul JavaScript. Pentru crashurile native este necesar Crashlytics NDK (Android) sau KSCrash (iOS). Error Boundary protejează doar stratul JavaScript al aplicației React Native.
Plasați Error Boundary la granițele modulelor semantice: un Boundary per ecran, unul per widget al unui dezvoltator terț, unul per formular complex. Aceasta izolează erorile și permite utilizatorului să continue lucrul în restul părților aplicației. Boundaryul rădăcină trebuie să existe întotdeauna — în cazul erorilor critice în componentele comune de navigație sau provideri. Fiecare Boundary răspunde pentru propriul fragment de interfață și nu afectează componentele învecinate la apariția unei erori.
Transmiteți întotdeauna eroarea către Crashlytics sau Sentry prin componentDidCatch. Adăugați context: numele ecranului, userId, versiunea aplicației, parametrii de navigație. În Sentry sunt disponibile breadcrumbs — secvența acțiunilor utilizatorului înainte de eroare. Pentru analiza frecvenței erorilor non-fatal, folosiți dashboardurile Crashlytics cu grupare pe issue.
Nu folosiți un fallback „gol” — creați o interfață semnificativă. Setul recomandat pentru React Native: mesaj de eroare (prietenos pentru utilizator, nu tehnic), buton „Reîncearcă”, link către suport sau chat. Evitați un View gol — utilizatorul va crede că aplicația s-a defectat complet și o va închide. Fallbackul trebuie integrat în designul general al aplicației.
Testați fiecare Error Boundary cu React Testing Library sau React Native Testing Library. Creați o componentă-trigger care aruncă o eroare la randare și verificați că fallback UI este afișat. Pentru testele de integrare, folosiți storybook cu diferite stări ale Error Boundary: normală, eroare, stare după resetare. Testarea automatizată a Boundary garantează că la modificarea componentei, fallback UI continuă să funcționeze corect în production. Acoperirea cu teste a fiecărui Boundary trebuie să fie o cerință obligatorie de code review pentru proiectele React Native.
Întrebări frecvente
React implementează Error Boundary doar prin componente de clasă, deoarece este necesar accesul la metodele de ciclu de viață componentDidCatch și getDerivedStateFromError. Componentele funcționale nu au astfel de metode. Biblioteca react-error-boundary oferă un wrapper gata făcut cu API de hookuri pentru ușurința utilizării.
Impactul este minim — Error Boundary adaugă o verificare a stării la fiecare randare a arborelui copil. Compararea state.hasError este o operație O(1) cu complexitate constantă. În absența erorilor, overheadul este inexistent. Doar la apariția unei erori, Boundary execută o randare suplimentară a fallback UI.
Nu, sunt suficiente 2–3 niveluri: Boundary rădăcină pentru întreaga aplicație, Boundary de ecran pentru fiecare ramură de navigație și Boundary local pentru widgeturile critice (formular de plată, hartă, chat). Un număr excesiv de Boundary complică arhitectura fără un beneficiu semnificativ.
Error Boundary și Suspense sunt independente: Suspense captează încărcarea (Promise în așteptare în React 18+), Error Boundary captează erorile de randare. Pot fi combinate: <ErrorBoundary><Suspense><Component /></Suspense></ErrorBoundary>. Suspense se execută primul la încărcare, Error Boundary — la eroarea componentei încărcate.
try-catch captează erori în codul imperativ sincron, dar nu poate intercepta erorile de randare JSX. Error Boundary este special conceput pentru UI declarativ: interceptează erorile în render, lifecycle-hookuri și constructorii componentelor copil, ceea ce try-catch nu poate face din cauza particularităților randării React.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și