Error Boundary — какво е, компонент React Native и обработка на грешки

Автор: IT Sectr Публикувано: 2026-05-27 Време за четене: 8 мин

Error Boundary е React компонент, който улавя JavaScript грешки в своето дъщерно дърво от компоненти и показва резервен интерфейс вместо страница за срив. В контекста на React Native предотвратява пълния срив на приложението при нефатални грешки при рендиране. Според React Documentation, 2024, error boundary улавя грешки в render методите, lifecycle-hooks и конструкторите на дъщерни компоненти, позволявайки на приложението да продължи работа. В React Native това е особено критично, тъй като мобилното приложение не се презарежда с F5 — потребителят губи цялата сесия.

Основни точки

  • Error Boundary — React компонент за улавяне на грешки при рендиране в дъщерното дърво
  • ComponentDidCatch — метод на жизнения цикъл, който получава грешката и информация за стека
  • Fallback UI — резервен интерфейс, показван вместо счупения компонент
  • React Native използва Error Boundary за предотвратяване на пълен срив на приложението
  • Ограничение — Error Boundary не улавя грешки в асинхронен код и event-обработчици

Какво е Error Boundary

Error Boundary е механизъм на React за graceful degradation при грешки при рендиране. Въведен в React 16 (2017) като компонент-обвивка, имплементиращ един от двата метода на жизнения цикъл: static getDerivedStateFromError или componentDidCatch. Error Boundary позволява на потребителя да види смислено съобщение вместо празен бял екран или пълен срив на приложението.

Как се появи Error Boundary

Преди React 16 всяка необработена грешка в render водеше до срив на цялото приложение с демонтиране на цялото DOM дърво. В уеб приложенията това означаваше празен бял екран, в React Native — пълен срив на приложението с връщане към Home Screen. Екипът на React въведе Error Boundary като аналог на catch-блок за декларативен UI, заимствайки концепцията от подхода „остави го да се срине” в езика Erlang.

Значение за React Native

В React Native липсата на Error Boundary означава пълен срив на приложението при всяка грешка при рендиране. Потребителят губи цялата текуща сесия без възможност за възстановяване. Error Boundary в React Native е критично важен, тъй като мобилните приложения не се презареждат като уеб страници — потребителската сесия се губи безвъзвратно и потребителят трябва да започне всичко отначало.

Как работи Error Boundary в React Native

Error Boundary работи на ниво React дърво. Когато дъщерен компонент хвърли грешка в render или lifecycle, React не демонтира цялото дърво, а предава контрола на най-близкия Error Boundary по-нагоре в йерархията. Boundary извиква getDerivedStateFromError, задава state.hasError = true и рендира fallback UI вместо счупения клон от компоненти.

typescript
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 компонент

За създаване на Error Boundary трябва да имплементирате класов компонент с методите getDerivedStateFromError и/или componentDidCatch. Функционалните компоненти не могат да бъдат Error Boundary — React поддържа тази функционалност само за класови компоненти, тъй като е необходим достъп до методите на жизнения цикъл. В библиотеката react-error-boundary е налична готова имплементация с hooks API за удобство.

typescript
// Пример за използване на 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 hook, позволявайки нулиране на състоянието без презареждане. За типични проекти схемата с три нива на Boundary се счита за оптимална за React Native приложения.

Нулиране на състоянието на Error Boundary

След възникване на грешка потребителят може да натисне бутона „Опитай отново”, който нулира hasError на false и прендира отново дъщерното дърво. Механизмът Reset е важен за възстановяване на работоспособността на приложението без презареждане. В react-error-boundary се използва onReset callback, който може да изчисти кеша, да поиска отново данни или да актуализира състоянието по-нагоре в дървото.

Ограничения на Error Boundary

Error Boundary не улавя асинхронни грешки — грешки в setTimeout, setInterval, Promise, async/await. React не може да улови грешки извън цикъла на рендиране и lifecycle-hooks, тъй като те се изпълняват в други контексти на изпълнение. За асинхронни грешки е необходим отделен try-catch в обработчиците или глобален обработчик на събитието unhandledrejection.

Event-обработчици

Грешките в onClick, onChange и други event-обработчици не се улавят от Error Boundary, тъй като те се изпълняват извън React рендирането. Обработка на грешки за event-обработчици трябва да бъде вътре в самия обработчик чрез try-catch. Библиотеката react-error-boundary предоставя hook useErrorHandler за прехвърляне на грешки от event-обработчици към най-близкия Boundary.

Server-side rendering и Next.js

Error Boundary не работи от сървърна страна в Next.js или Gatsby. Методите getDerivedStateFromError и componentDidCatch не се извикват при SSR, тъй като методите на жизнения цикъл са достъпни само в браузъра. За сървърни грешки е необходима отделна стратегия: try-catch в getServerSideProps, fallback страници error.js (Next.js 13+) или глобален middleware.

Native слой на React Native

В React Native Error Boundary не предотвратява срив на ниво native модули. Native crash (segfault, out-of-memory, native изключение) се случва на ниво Objective-C или Java и не достига до JavaScript слоя. За native сривове е необходим Crashlytics NDK (Android) или KSCrash (iOS). Error Boundary защитава само JavaScript слоя на React Native приложението.

Най-добри практики за Error Boundary

Поставете Error Boundary на границите на смислови модули: един Boundary на екран, един на widget на външен разработчик, един на сложна форма. Това изолира грешките и позволява на потребителя да продължи работа в останалите части на приложението. Коренният Boundary трябва винаги да съществува — за критични грешки в общите навигационни компоненти или provider-и. Всеки Boundary отговаря за своя фрагмент от интерфейса и не влияе на съседните компоненти при възникване на грешка.

Логване и мониторинг

Винаги предавайте грешката на Crashlytics или Sentry чрез componentDidCatch. Добавяйте контекст: име на екрана, userId, версия на приложението, параметри за навигация. В Sentry са налични breadcrumbs — последователност от действия на потребителя преди грешката. За анализ на честотата на non-fatal грешки използвайте Crashlytics dashboard-и с групиране по issue.

Fallback UI

Не използвайте „гол” fallback — създайте смислен интерфейс. Препоръчителен комплект за React Native: съобщение за грешка (приятелско към потребителя, не техническо), бутон „Опитай отново”, връзка за поддръжка или чат. Избягвайте празен View — потребителят ще помисли, че приложението се е сринало напълно, и ще го затвори. Fallback трябва да бъде вграден в общия дизайн на приложението.

Тестване на Error Boundary

Тествайте всеки Error Boundary с React Testing Library или React Native Testing Library. Създайте trigger компонент, който хвърля грешка при рендиране, и проверете дали fallback UI се показва. За интеграционни тестове използвайте storybook с различни състояния на Error Boundary: нормално, грешка, състояние след нулиране. Автоматизираното тестване на Boundary гарантира, че при промяна на компонента fallback UI продължава да работи правилно в production. Покритието с тестове на всеки Boundary трябва да бъде задължително изискване за code review на React Native проекти.

Често задавани въпроси

Защо Error Boundary не работи с функционални компоненти?

React имплементира Error Boundary само чрез класови компоненти, защото е необходим достъп до методите на жизнения цикъл componentDidCatch и getDerivedStateFromError. Функционалните компоненти нямат такива методи. Библиотеката react-error-boundary предоставя готова класова обвивка с hooks API за удобство при използване.

Как Error Boundary влияе на производителността?

Влиянието е минимално — Error Boundary добавя проверка на състоянието при всяко рендиране на дъщерното дърво. Сравнението на state.hasError е O(1) операция с константна сложност. При липса на грешки overhead липсва. Само при възникване на грешка Boundary изпълнява допълнително рендиране на fallback UI.

Трябва ли всеки компонент да бъде обвит в Error Boundary?

Не, достатъчни са 2–3 нива: коренен Boundary за цялото приложение, екранен Boundary за всеки навигационен клон и локален Boundary за критични widget-и (платежна форма, карта, чат). Прекомерният брой Boundary усложнява архитектурата без значителна полза.

Как Error Boundary работи с Suspense в React 18+?

Error Boundary и Suspense са независими: Suspense улавя зареждане (pending Promise в React 18+), Error Boundary улавя грешки при рендиране. Те могат да се комбинират: <ErrorBoundary><Suspense><Component /></Suspense></ErrorBoundary>. Suspense се изпълнява първи при зареждане, Error Boundary — при грешка на заредения компонент.

Каква е разликата между Error Boundary и try-catch в React?

try-catch улавя грешки в синхронен императивен код, но не може да улови грешки при рендиране на JSX. Error Boundary е специално проектиран за декларативен UI: той улавя грешки в render, lifecycle-hooks и конструкторите на дъщерни компоненти, което try-catch не може да направи поради особеностите на React рендирането.

Резюме

  • Error Boundary — React компонент за улавяне на грешки при рендиране с показване на fallback UI
  • ComponentDidCatch — метод за логване на грешки, getDerivedStateFromError — за управление на състоянието на UI
  • React Native критично се нуждае от Error Boundary за предотвратяване на пълен срив на приложението
  • Ограничения — не улавя асинхронни грешки, грешки в event-обработчици, SSR и native слой
  • react-error-boundary — готова библиотека с hooks API за лесна интеграция в проекта
  • Нива на обвивка — коренен, екранен (препоръчва се) и локален за критични widget-и
  • Fallback UI трябва да бъде смислен: съобщение за грешка, бутон за повторен опит, контакт за поддръжка

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също