import { Component } from 'react'; import { IconAlertTriangle, IconRefresh, IconHome } from '@tabler/icons-react'; /** * ErrorBoundary - глобальный обработчик ошибок React * Ловит ошибки рендеринга и показывает fallback UI */ class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, error: null, errorInfo: null, errorCount: 0 }; } static getDerivedStateFromError(error) { return { hasError: true }; } componentDidCatch(error, errorInfo) { // Логируем ошибку console.error('ErrorBoundary caught an error:', error, errorInfo); // Отправляем в мониторинг (если настроен) this.logErrorToService(error, errorInfo); this.setState(prevState => ({ error, errorInfo, errorCount: prevState.errorCount + 1 })); } logErrorToService(error, errorInfo) { // Можно интегрировать с Sentry, LogRocket и т.д. try { if (typeof window !== 'undefined' && window.notify?.error) { window.notify.error('Произошла критическая ошибка приложения', { error: error.toString(), componentStack: errorInfo?.componentStack }); } } catch (e) { console.error('Failed to log error:', e); } } handleReset = () => { this.setState({ hasError: false, error: null, errorInfo: null }); // Очищаем localStorage если ошибка повторяется if (this.state.errorCount > 2) { try { localStorage.clear(); sessionStorage.clear(); } catch (e) { console.error('Failed to clear storage:', e); } } // Перезагружаем страницу если много ошибок if (this.state.errorCount > 3) { window.location.href = '/'; } }; handleReload = () => { window.location.reload(); }; handleGoHome = () => { window.location.href = '/'; }; render() { if (this.state.hasError) { return (
Произошла ошибка
{this.state.error?.message || 'Что-то пошло не так. Попробуйте обновить страницу.'}
{process.env.NODE_ENV === 'development' && this.state.errorInfo && (
{this.state.error?.toString()}
{'\n\n'}
{this.state.errorInfo?.componentStack}
Ошибка повторяется ({this.state.errorCount} раз). {this.state.errorCount > 2 && ' При следующей попытке кэш будет очищен.'} {this.state.errorCount > 3 && ' Следующая попытка приведёт к полной перезагрузке.'}