Error Boundary је React компонента која хвата JavaScript грешке у свом стаблу компоненти и приказује резервни интерфејс уместо crash странице. У контексту React Native-а спречава потпуни пад апликације при нефаталним грешкама рендеровања. Према React Documentation, 2024, error boundary хвата грешке у render методама, lifecycle-хуковима и конструкторима компоненти, омогућавајући апликацији да настави рад. У React Native-у је ово посебно критично, јер се мобилна апликација не освежава са F5 — корисник губи целу сесију.
Главне тачке
Error Boundary је React механизам за постепено деградирање при грешкама рендеровања. Уведен у React 16 (2017) као компонента-омотач која имплементира једну од две методе животног циклуса: static getDerivedStateFromError или componentDidCatch. Error Boundary омогућава приказ смислене поруке уместо празног белог екрана или потпуног пада апликације.
Пре React 16, свака необрађена грешка у render-у доводила је до пада целе апликације са демонтирањем целог DOM стабла. У веб апликацијама то је значило празан бели екран, у React Native-у — потпуни пад апликације са повратком на Home Screen. React тим је увео Error Boundary као аналогон catch-блока за декларативни UI, позајмивши концепт из приступа „пусти да се сруши” у језику Erlang.
У React Native-у, одсуство Error Boundary значи потпуни пад апликације при било којој грешци рендеровања. Корисник губи целу тренутну сесију без могућности опоравка. Error Boundary у React Native-у је критично важан, јер се мобилне апликације не освежавају као веб странице — корисничка сесија се неповратно губи и корисник мора да почне све изнова.
Error Boundary ради на нивоу React стабла. Када компонента избаци грешку у render-у или lifecycle-у, React не демонтира цело стабло, већ прослеђује контролу најближем Error Boundary-у изнад у хијерархији. Boundary позива getDerivedStateFromError, поставља state.hasError = true и рендерује fallback UI уместо покварене гране компоненти.
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("Ухваћено од стране boundary:", error)
Crashlytics.recordException(error)
}
render() {
if (this.state.hasError) {
return this.props.fallback || <FallbackUI />
}
return this.props.children
}
}
getDerivedStateFromError поставља стање за рендеровање fallback UI-ја — то је статичка метода која се позива у фази рендеровања пре потврде измена. componentDidCatch се извршава у фази потврде и намењен је споредним ефектима: логирање, слање crash-извештаја у Crashlytics, аналитика. Две методе деле одговорност између управљања стањем UI-ја и споредних акција.
За креирање Error Boundary потребно је имплементирати класну компоненту са методама getDerivedStateFromError и/или componentDidCatch. Функционалне компоненте не могу бити Error Boundary — React подржава ову функционалност само за класне компоненте, јер је потребан приступ методама животног циклуса. У библиотеци react-error-boundary доступна је готова имплементација са хуковским API-јем за практичност.
// Пример коришћења Error Boundary у React Native
import { ErrorBoundary } from "react-error-boundary"
const FallbackComponent = ({ error, resetError }: FallbackProps) => (
<View style={styles.container}>
<Text>Нешто је пошло наопако</Text>
<Text>{error.message}</Text>
<Button title="Покушај поново" onPress={resetError} />
</View>
)
const App = () => (
<SafeAreaView>
<ErrorBoundary FallbackComponent={<FallbackComponent />}>
<UserProfile userId={"123"} />
</ErrorBoundary>
<BottomNavigation />
</SafeAreaView>
)
Нивои омотача — Error Boundary се може поставити на различите нивое хијерархије. Један глобални Boundary на корену апликације приказаће fallback UI при било којој грешци, али навигација ће и даље радити. Више Boundary на нивоу екрана омогућава изолацију грешака: ако се један екран поквари, остали настављају да раде независно. react-error-boundary поједностављује Reset механизам кроз useErrorBoundary хук, омогућавајући ресетовање стања без поновног учитавања. За типичне пројекте, шема са три нивоа Boundary сматра се оптималном за React Native апликације.
Након појаве грешке, корисник може притиснути дугме „Покушај поново”, које ресетује hasError на false и поново рендерује стабло. Reset механизам је важан за обнављање радне способности апликације без поновног учитавања. У react-error-boundary користи се onReset callback, који може очистити кеш, поново захтевати податке или ажурирати стање изнад у стаблу.
Error Boundary не хвата асинхроне грешке — грешке у setTimeout, setInterval, Promise, async/await. React не може пресрести грешке ван циклуса рендеровања и lifecycle-хуюва, јер се оне извршавају у другим контекстима извршења. За асинхроне грешке потребан је посебан try-catch у руководиоцима или глобални руководилац unhandledrejection догађаја.
Грешке у onClick, onChange и другим event-руководиоцима не хвата Error Boundary, јер се оне извршавају ван React рендеровања. Обрада грешака за event-руководиоце треба да буде унутар самог руководиоца кроз try-catch. Библиотека react-error-boundary пружа хук useErrorHandler за прослеђивање грешака из event-руководилаца у најближи Boundary.
Error Boundary не ради на серверској страни у Next.js или Gatsby-ју. Методе getDerivedStateFromError и componentDidCatch се не позивају при SSR-у, јер су методе животног циклуса доступне само у прегледачу. За серверске грешке потребна је посебна стратегија: try-catch у getServerSideProps, fallback странице error.js (Next.js 13+) или глобални middleware.
У React Native-у, Error Boundary не спречава пад на нивоу нативних модула. Нативни crash (segfault, out-of-memory, нативни изузетак) дешава се на нивоу Objective-C или Java и не стиже до JavaScript слоја. За нативне крашеве потребан је Crashlytics NDK (Android) или KSCrash (iOS). Error Boundary штити само JavaScript слој React Native апликације.
Поставите Error Boundary на границе смисаоних модула: један Boundary по екрану, један по widget-у спољног програмера, један по сложеној форми. То изолује грешке и омогућава кориснику да настави рад у осталим деловима апликације. Коренски Boundary мора увек постојати — за случај критичних грешака у заједничким компонентама навигације или провајдерима. Сваки Boundary одговоран је за свој фрагмент интерфејса и не утиче на суседне компоненте при настанку грешке.
Увек проследите грешку у Crashlytics или Sentry кроз componentDidCatch. Додајте контекст: назив екрана, userId, верзију апликације, параметре навигације. У Sentry-ју су доступни breadcrumbs — секвенца радњи корисника пре грешке. За анализу учесталости non-fatal грешака користите Crashlytics панеле са груписањем по issue.
Немојте користити „голи” fallback — направите смислени интерфејс. Препоручени сет за React Native: порука о грешци (прилагођена кориснику, не техничка), дугме „Покушај поново”, линк за подршку или ћаскање. Избегавајте празан View — корисник ће помислити да се апликација потпуно покварила и затвориће је. Fallback треба да буде уграђен у општи дизајн апликације.
Тестирајте сваки Error Boundary помоћу React Testing Library или React Native Testing Library. Направите компоненту-окидач која избацује грешку при рендеровању и проверите да се fallback UI приказује. За интеграционе тестове користите storybook са различитим стањима Error Boundary: нормално, грешка, стање након ресетовања. Аутоматизовано тестирање Boundary гарантује да при промени компоненте fallback UI наставља да ради исправно у production-у. Покривеност тестовима сваког Boundary треба да буде обавезан захтев code review-а за React Native пројекте.
Често постављана питања
React имплементира Error Boundary само кроз класне компоненте, јер је потребан приступ методама животног циклуса componentDidCatch и getDerivedStateFromError. Функционалне компоненте немају такве методе. Библиотека react-error-boundary пружа готови класни омотач са хуковским API-јем за практичност коришћења.
Утицај је минималан — Error Boundary додаје проверу стања при сваком рендеровању стабла. Поређење state.hasError је O(1) операција са константном сложеношћу. При одсуству грешака overhead не постоји. Само при настанку грешке Boundary врши додатно рендеровање fallback UI-ја.
Не, довољно је 2–3 нивоа: коренски Boundary за целу апликацију, екрански Boundary за сваку навигациону грану и локални Boundary за критичне widgetе (формулар за плаћање, мапу, ћаскање). Превелики број Boundary компликује архитектуру без значајне користи.
Error Boundary и Suspense су независни: Suspense хвата учитавање (pending Promise у React 18+), Error Boundary хвата грешке рендеровања. Могу се комбиновати: <ErrorBoundary><Suspense><Component /></Suspense></ErrorBoundary>. Suspense се први извршава при учитавању, Error Boundary — при грешци учитане компоненте.
try-catch хвата грешке у синхроном императивном коду, али не може пресрести грешке рендеровања JSX-а. Error Boundary је посебно дизајниран за декларативни UI: пресреће грешке у render-у, lifecycle-хуковима и конструкторима компоненти, што try-catch не може због карактеристика React рендеровања.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође