Ошибки в компонентах пользовательского интерфейса могут приводить к
полной остановке приложения, некорректному отображению интерфейса или
нарушению работы других частей приложения. Для их перехвата в Preact
используется механизм, схожий с React, через error
boundaries и метод жизненного цикла
componentDidCatch.
Error Boundary — это компонент класса, который перехватывает ошибки в своих дочерних компонентах. Такие ошибки могут возникать в следующих случаях:
Компоненты функционального типа напрямую не могут использовать
componentDidCatch, поэтому для перехвата ошибок необходим
классовый компонент.
Пример базового error boundary:
import { Component, h } from 'preact';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
console.error('Ошибка в компоненте:', error);
console.error('Информация о компоненте:', info);
this.setState({ hasError: true });
}
render() {
if (this.state.hasError) {
return <h1>Произошла ошибка.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
Ключевые моменты:
componentDidCatch(error, info) получает два
аргумента:
error — объект ошибки.info — объект с информацией о компоненте
(componentStack).После перехвата ошибки состояние компонента обычно обновляется, чтобы отобразить запасной UI.
Все дочерние компоненты, обернутые в ErrorBoundary,
защищены от остановки приложения.
Оборачивать error boundary можно вокруг отдельных компонентов или целых разделов приложения:
<ErrorBoundary>
<MyComplexComponent />
</ErrorBoundary>
Если внутри MyComplexComponent возникнет ошибка во время
рендера, приложение не упадет полностью. Вместо этого отобразится
сообщение из ErrorBoundary.
componentDidCatch, начиная с версии
X (следует проверять актуальную документацию), но не все расширенные
возможности React доступны по умолчанию.preact/compat.Сбор информации для аналитики:
componentDidCatch(error, info) {
// Локальное логирование
console.error(error, info);
// Отправка на сервер
fetch('/api/log-error', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ error: error.toString(), stack: info.componentStack })
});
this.setState({ hasError: true });
}
Динамическое восстановление:
Можно внедрить кнопку “Попробовать снова”, которая сбрасывает состояние error boundary:
render() {
if (this.state.hasError) {
return (
<div>
<h1>Произошла ошибка.</h1>
<button onCl ick={() => this.setState({ hasError: false })}>
Попробовать снова
</button>
</div>
);
}
return this.props.children;
}
componentDidCatch не ловит ошибки в асинхронных
колбэках, обработчиках событий или внутри setTimeout..catch() или глобальный обработчик
window.onerror.componentDidCatch только для визуального
fallback и логирования, не для управления логикой приложения.Эффективное использование componentDidCatch обеспечивает
устойчивость интерфейса, предотвращает поломку всего
приложения при ошибках и позволяет аккуратно собирать информацию для
отладки и аналитики.