← Назад к вопросам
Какие функции в React отвечают за перехват ошибок?
2.0 Middle🔥 253 комментариев
#React#Архитектура и паттерны
Комментарии (3)
🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Обработка ошибок в React: Error Boundaries и прочее
Обработка ошибок в React — важный аспект надежного приложения. Не все ошибки одинаковы, и React предоставляет несколько механизмов для их перехвата и обработки.
Error Boundaries: перехват ошибок в компонентах
Error Boundary — это компонент, который перехватывает JavaScript ошибки в дочерних компонентах, логирует эти ошибки и показывает fallback UI вместо краша.
// Error Boundary компонент (class component)
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// Обновить state так, чтобы при следующем рендере был fallback
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Залогировать ошибку в сервис логирования
console.error('Error caught:', error, errorInfo);
logErrorToService(error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Что-то пошло не так. Попробуйте обновить страницу.</h1>;
}
return this.props.children;
}
}
// Использование
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
Что перехватывает Error Boundary
Error Boundary перехватывает:
- Ошибки в рендере (render)
- Ошибки в lifecycle методах
- Ошибки в конструкторах дочерних компонентов
Error Boundary НЕ перехватывает:
- Асинхронные ошибки (try/catch в Promise, setTimeout)
- Обработчики событий (onClick, onChange)
- Ошибки в самом Error Boundary
// Примеры ошибок, которые НЕ перехватываются Error Boundary
function MyComponent() {
useEffect(() => {
// Ошибка в effect — не перехватится
fetch('/api/data')
.then(res => res.json())
.catch(error => {
// Нужно обрабатывать вручную
console.error(error);
});
}, []);
const handleClick = () => {
// Ошибка в обработчике — не перехватится
throw new Error('Клик вызвал ошибку');
};
return <button onClick={handleClick}>Клик</button>;
}
Обработка асинхронных ошибок
Для асинхронных ошибок нужна ручная обработка:
function MyComponent() {
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const data = await response.json();
// обработать данные
} catch (err) {
// Поймать и сохранить ошибку
setError(err.message);
} finally {
setIsLoading(false);
}
};
fetchData();
}, []);
if (error) {
return <div className="error">Ошибка: {error}</div>;
}
if (isLoading) {
return <div>Загрузка...</div>;
}
return <div>Данные загружены</div>;
}
Обработка ошибок в обработчиках событий
Ошибки в onClick, onChange и т.д. нужно ловить с try/catch:
function ClickHandler() {
const handleClick = async () => {
try {
// Может быть асинхронная операция
const result = await riskyOperation();
console.log(result);
} catch (error) {
// Обработать ошибку
console.error('Ошибка в обработчике:', error);
// Показать пользователю сообщение об ошибке
alert('Операция не удалась: ' + error.message);
}
};
return <button onClick={handleClick}>Выполнить</button>;
}
Полный пример: комбинированная обработка ошибок
// ErrorBoundary для перехвата ошибок в рендере
class ErrorBoundary extends React.Component {
state = { hasError: false, error: null };
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Отправить в сервис логирования (Sentry, LogRocket и т.д.)
reportError({ error, errorInfo });
}
render() {
if (this.state.hasError) {
return (
<div className="error-page">
<h1>Упс, что-то пошло не так</h1>
<button onClick={() => window.location.reload()}>
Обновить страницу
</button>
</div>
);
}
return this.props.children;
}
}
// Компонент с асинхронной обработкой
function DataFetcher() {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const fetchData = useCallback(async () => {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const result = await res.json();
setData(result);
setError(null); // Очистить старые ошибки
} catch (err) {
setError(err.message);
setData(null);
}
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
if (error) {
return (
<div className="error-message">
<p>{error}</p>
<button onClick={fetchData}>Попробовать снова</button>
</div>
);
}
return <div>{data ? JSON.stringify(data) : 'Загрузка...'}</div>;
}
// Использование
export default function App() {
return (
<ErrorBoundary>
<DataFetcher />
</ErrorBoundary>
);
}
Сервисы логирования ошибок
Для production используй сервисы вроде Sentry, LogRocket:
import * as Sentry from "@sentry/react";
// Инициализация
Sentry.init({
dsn: process.env.REACT_APP_SENTRY_DSN,
environment: process.env.NODE_ENV,
tracesSampleRate: 0.1,
});
// Wrapper для Error Boundary
const SentryErrorBoundary = Sentry.withErrorBoundary(MyComponent, {
fallback: <div>Что-то пошло не так</div>,
showDialog: true,
});
Мой подход к обработке ошибок
- Error Boundary для ловли ошибок в рендере
- try/catch для асинхронных операций
- Обработчики ошибок в обработчиках событий
- Сервис логирования (Sentry) для monitoring в production
- Fallback UI для каждого типа ошибки — не просто красный экран
Правильная обработка ошибок — это не только про поимку, но и про предоставление пользователю информации о том, что произошло и как исправить.