Что такое error boundary в React?
Error Boundary в React
Error boundary (граница ошибки) — специальный класс-компонент, который реализует один или оба метода жизненного цикла: static getDerivedStateFromError() и componentDidCatch(). Благодаря им компонент перехватывает необработанные ошибки, возникающие при рендере, в методах жизненного цикла и в конструкторах дочерних компонентов.
Как это работает
Когда дочерний компонент выбрасывает исключение во время рендера, React ищет ближайший error boundary вверх по дереву компонентов. Если он найден — вызывается getDerivedStateFromError, который обновляет состояние, и на следующем рендере отображается fallback-UI. Метод componentDidCatch вызывается уже после рендера и предназначен для логирования ошибки.
Что error boundary не перехватывает
- Ошибки в обработчиках событий (используйте обычный
try/catch) - Асинхронный код (
setTimeout,fetch, промисы) - Ошибки серверного рендеринга (SSR)
- Ошибки внутри самого error boundary
Функциональные компоненты
Error boundary нельзя написать как функциональный компонент — для этого обязательно нужен класс. Однако существуют библиотеки, например react-error-boundary, которые предоставляют хук useErrorBoundary и компонент <ErrorBoundary> с удобным API.
Стратегия размещения
Error boundary можно оборачивать как всё приложение целиком (грубая защита), так и отдельные виджеты или маршруты — тогда падение одной части страницы не уронит остальные.
Пример
См. раздел с примерами кода ниже.
Восстановление после ошибки
Через componentDidCatch можно отправить ошибку в систему мониторинга (Sentry, Datadog). Кнопка «Попробовать снова» реализуется сбросом состояния error boundary — например методом resetErrorBoundary из react-error-boundary.
Что хочет услышать интервьюер
Понимание того, что error boundary — это именно класс-компонент, и объяснение почему (хуки не покрывают методы getDerivedStateFromError/componentDidCatch)
Знание двух ключевых методов жизненного цикла и разницы между ними: getDerivedStateFromError для рендера fallback-UI, componentDidCatch для логирования
Чёткое перечисление сценариев, которые error boundary НЕ перехватывает (обработчики событий, async-код)
Понимание стратегии размещения границ ошибок в дереве компонентов
Упоминание react-error-boundary как современного практичного решения
Пример: Классический error boundary
import React, { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
fallback: ReactNode;
children: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
}
class ErrorBoundary extends Component<Props, State> {
state: State = { hasError: false, error: null };
// Вызывается во время рендера — обновляем state, чтобы показать fallback
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
// Вызывается после рендера — подходит для логирования
componentDidCatch(error: Error, info: ErrorInfo): void {
console.error('ErrorBoundary поймал ошибку:', error, info.componentStack);
// sendToSentry(error, info);
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}
// Использование
function App() {
return (
<ErrorBoundary fallback={<p>Что-то пошло не так. Попробуйте обновить страницу.</p>}>
<UserProfile />
</ErrorBoundary>
);
}
Пример: Современный подход с react-error-boundary
import { ErrorBoundary, useErrorBoundary } from 'react-error-boundary';
function FallbackComponent({ error, resetErrorBoundary }: {
error: Error;
resetErrorBoundary: () => void;
}) {
return (
<div role="alert">
<p>Произошла ошибка: {error.message}</p>
<button onClick={resetErrorBoundary}>Попробовать снова</button>
</div>
);
}
// Внутри дочернего компонента можно вручную сообщить об ошибке
function DataLoader() {
const { showBoundary } = useErrorBoundary();
async function fetchData() {
try {
const data = await api.getData();
return data;
} catch (err) {
// Пробрасываем async-ошибку в ближайший error boundary
showBoundary(err);
}
}
return <button onClick={fetchData}>Загрузить</button>;
}
function App() {
return (
<ErrorBoundary
FallbackComponent={FallbackComponent}
onError={(error, info) => console.error(error, info)}
>
<DataLoader />
</ErrorBoundary>
);
}
Типичные ошибки
Попытка написать error boundary как функциональный компонент — это невозможно без сторонней обёртки
Уверенность, что error boundary поймает ошибку в onClick или других обработчиках событий
Путаница между getDerivedStateFromError (статический, для рендера) и componentDidCatch (для side-effects/логирования)
Один глобальный error boundary на всё приложение вместо точечной расстановки по критичным блокам
Забывают о том, что error boundary не ловит асинхронные ошибки (промисы, async/await)


