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

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

Error Boundary — это компонент React, который перехватывает JavaScript-ошибки в своём дочернем дереве компонентов и отображает запасной интерфейс вместо crash-страницы. В контексте React Native он предотвращает полный сбой приложения при нефатальных ошибках рендеринга. По данным React Documentation, 2024, error boundary ловит ошибки в методах render, lifecycle-хуках и конструкторах дочерних компонентов, позволяя приложению продолжить работу. В React Native это особенно критично, так как мобильное приложение не перезагружается по F5 — пользователь теряет сеанс целиком.

Главное

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

Что такое Error Boundary

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

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

До React 16 любая необработанная ошибка в render приводила к crash всего приложения с размонтированием всего DOM-дерева. В web-приложениях это означало пустой белый экран, в React Native — полный crash приложения с возвратом на Home Screen. React-команда ввела Error Boundary как аналог catch-блока для декларативного UI, заимствовав концепцию из подхода «let it crash» в языке Erlang.

Значение для React Native

В React Native отсутствие Error Boundary означает полный crash приложения при любой ошибке рендеринга. Пользователь теряет весь текущий сеанс без возможности восстановления. Error Boundary в React Native критически важен, поскольку мобильные приложения не перезагружаются как веб-страницы — user session безвозвратно теряется, и пользователю приходится начинать всё заново.

Как работает 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("Caught by 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 поддерживает эту функциональность только для классовых компонентов, поскольку требуется доступ к lifecycle-методам. В библиотеке react-error-boundary доступна готовая реализация с хуковым 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 хук, позволяя сбросить состояние без перезагрузки. Для типовых проектов схема с тремя уровнями Boundary считается оптимальной для React Native приложений.

Сброс состояния Error Boundary

После возникновения ошибки пользователь может нажать кнопку «Повторить», которая сбрасывает hasError в false и перерендеривает дочернее дерево. Reset-механизм важен для восстановления работоспособности приложения без перезагрузки. В react-error-boundary используется onReset callback, который может очищать кэш, перезапрашивать данные или обновлять состояние выше по дереву.

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

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

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

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

Server-side rendering и Next.js

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

React Native native-слой

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

Лучшие практики Error Boundary

Размещайте Error Boundary на границах смысловых модулей: один Boundary на экран, один на виджет стороннего разработчика, один на сложную форму. Это изолирует ошибки и позволяет пользователю продолжать работу в остальных частях приложения. Корневой Boundary должен быть всегда — на случай критических ошибок в общих компонентах навигации или провайдерах. Каждый Boundary отвечает за свой фрагмент интерфейса и не влияет на соседние компоненты при возникновении ошибки.

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

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

Fallback UI

Не используйте «голый» fallback — делайте осмысленный интерфейс. Рекомендуемый набор для React Native: сообщение об ошибке (user-friendly, не техническое), кнопка «Повторить», ссылка на поддержку или чат. Избегайте пустого View — пользователь подумает, что приложение сломалось полностью, и закроет его. Fallback должен быть встроен в общий дизайн приложения.

Тестирование Error Boundary

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

Часто задаваемые вопросы

Почему Error Boundary не работает с функциональными компонентами?

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

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

Влияние минимально — Error Boundary добавляет проверку состояния при каждом рендере дочернего дерева. Сравнение state.hasError — это O(1) операция с константной сложностью. При отсутствии ошибок overhead отсутствует. Только при возникновении ошибки Boundary выполняет дополнительный рендер fallback UI.

Нужно ли оборачивать каждый компонент в Error Boundary?

Нет, достаточно 2–3 уровней: корневой Boundary для всего приложения, экранный Boundary для каждой навигационной ветки и локальный Boundary для критических виджетов (платёжная форма, карта, чат). Чрезмерное количество Boundary усложняет архитектуру без значительной пользы.

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

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

Чем отличается Error Boundary от try-catch в React?

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

Итоги

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

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

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также