Границы ошибок
Если компонент бросит исключение во время отрисовки, React уберёт со страницы всё приложение — пользователь увидит пустой экран. Граница ошибок (error boundary) — компонент-обёртка, который ловит такие ошибки в своих детях и показывает вместо них запасной интерфейс. Остальная часть страницы продолжает работать.
Что ломает страницу
Пусть в блоге статья пришла без заголовка, а компонент на это не рассчитан:
// src/components/PostCard.jsx
export default function PostCard({ post }) {
return <h2>{post.title.toUpperCase()}</h2>;
}Если post.title равен undefined, вызов toUpperCase() бросит TypeError. Без границы ошибок вся страница станет белой, а ошибка появится только в консоли.
Компонент-граница
Границу ошибок можно написать только классом — для неё нет хука. Создайте src/components/ErrorBoundary.jsx один раз и используйте во всём проекте:
// src/components/ErrorBoundary.jsx
import { Component } from 'react';
export default class ErrorBoundary extends Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error('Ошибка в компоненте:', error, info.componentStack);
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}getDerivedStateFromError вызывается при ошибке в любом потомке и переключает состояние. componentDidCatch — место, чтобы записать ошибку в журнал или отправить в сервис мониторинга. Пока ошибки нет, граница просто выводит children.
Использование
Оберните опасную часть страницы и передайте запасную разметку в проп fallback:
// src/pages/HomePage.jsx
import ErrorBoundary from '../components/ErrorBoundary.jsx';
import PostList from '../components/PostList.jsx';
export default function HomePage() {
return (
<>
<h1>Блог</h1>
<ErrorBoundary fallback={<p>Не удалось показать статьи.</p>}>
<PostList />
</ErrorBoundary>
</>
);
}Если в PostList или любой карточке внутри случится ошибка, вместо списка появится «Не удалось показать статьи.», а заголовок «Блог» и меню останутся на месте.
Где ставить границы
| Место | Что защищает |
|---|---|
Вокруг всего App | Хотя бы сообщение вместо белого экрана |
| Вокруг каждой страницы в макете | Ошибка на странице не ломает меню |
| Вокруг независимого блока | Комментарии упали, статья осталась |
Готовая библиотека
Чтобы не писать класс, можно установить пакет react-error-boundary (npm install react-error-boundary). Его компонент ErrorBoundary принимает тот же проп fallback и умеет сбрасывать ошибку кнопкой «Попробовать снова».
Частая ошибка
Граница ловит только ошибки во время отрисовки и в эффектах. Ошибки в обработчиках событий и в асинхронном коде она не видит:
// Граница НЕ поймает эту ошибку: она в обработчике клика.
<button onClick={() => { throw new Error('Сбой'); }}>Удалить</button>Такие ошибки обрабатывайте сами через try/catch и показывайте сообщение через состояние, как в уроке про загрузку данных.