11 KiB
⚡ Быстрый старт - Обработка ошибок
5-минутное руководство по использованию новой системы обработки ошибок
🎯 Основные сценарии
1️⃣ Простая загрузка данных
import { useErrorHandler } from '../hooks/useErrorHandler';
import api from '../lib/api';
function MyComponent() {
const { withErrorHandler } = useErrorHandler();
const loadData = withErrorHandler(
async () => {
const response = await api.get('/domains-new');
setData(response.data);
},
{ successMessage: 'Данные загружены' }
);
return <button onClick={loadData}>Загрузить</button>;
}
Что происходит:
- ✅ Автоматический retry при сбоях (до 3 раз)
- ✅ User-friendly сообщения об ошибках
- ✅ Успешное уведомление при загрузке
- ✅ Нет дубликатов уведомлений
2️⃣ Кнопка с retry
import RetryButton from '../components/RetryButton';
import api from '../lib/api';
function MyComponent() {
const [loading, setLoading] = useState(false);
const saveData = async () => {
setLoading(true);
try {
await api.post('/domains-new', { domains: [...] });
} finally {
setLoading(false);
}
};
return (
<RetryButton
onRetry={saveData}
loading={loading}
>
Сохранить
</RetryButton>
);
}
Что происходит:
- ✅ Показывает индикатор загрузки
- ✅ Автоматический retry при ошибках
- ✅ Блокирует повторные клики
3️⃣ Ручная обработка ошибок
import { useErrorHandler } from '../hooks/useErrorHandler';
import api from '../lib/api';
function MyComponent() {
const { handleError, handleSuccess } = useErrorHandler();
const deleteItem = async (id) => {
try {
await api.delete(`/domains-new/${id}`);
handleSuccess('Домен удалён');
} catch (error) {
handleError(error, {
component: 'MyComponent',
action: 'delete',
itemId: id
});
}
};
return <button onClick={() => deleteItem(123)}>Удалить</button>;
}
Что происходит:
- ✅ Полный контроль над обработкой
- ✅ Контекст для отладки
- ✅ User-friendly сообщения
🔧 Настройка (уже сделано!)
Все компоненты уже интегрированы в App.jsx:
<ErrorBoundary> {/* Ловит ошибки React */}
<Router>
<QueryClientProvider>
<NotifyProvider>
<NetworkErrorHandler /> {/* Мониторит сеть */}
<MainLayout />
</NotifyProvider>
</QueryClientProvider>
</Router>
</ErrorBoundary>
Ничего дополнительно настраивать не нужно! 🎉
📦 Что уже работает автоматически
✅ Автоматический Retry
| Метод | Ошибка | Попытки |
|---|---|---|
| GET | Network | 3 |
| GET | Timeout | 2 |
| GET | Server (5xx) | 2 |
| POST/PUT | Network | 1 |
| POST/PUT | Timeout | 1 |
✅ User-Friendly сообщения
Технические ошибки → Понятные сообщения
ECONNABORTED→ "Сервер не отвечает"500 Internal Server Error→ "Ошибка сервера. Попробуйте позже"400 Bad Request→ "Ошибка валидации. Проверьте данные"404 Not Found→ "Запрашиваемый ресурс не найден"
✅ Offline Detection
- Красный баннер при потере связи
- Зелёный баннер при восстановлении
- Автоматическое скрытие через 3 секунды
✅ Error Boundary
- Ловит ошибки рендеринга React
- Показывает красивую страницу ошибки
- Кнопки восстановления
🎨 Типы уведомлений
const { handleSuccess, handleError, handleWarning, handleInfo } = useErrorHandler();
handleSuccess('Данные сохранены'); // 🟢 Зелёное
handleError('Не удалось загрузить'); // 🔴 Красное
handleWarning('Изменения не сохранены'); // 🟡 Жёлтое
handleInfo('Проверьте обновления'); // 🔵 Синее
🚀 Продвинутые примеры
React Query интеграция
import { useQuery } from '@tanstack/react-query';
import { useErrorHandler } from '../hooks/useErrorHandler';
import api from '../lib/api';
function MyComponent() {
const { handleError } = useErrorHandler();
const { data, isLoading, refetch } = useQuery({
queryKey: ['domains'],
queryFn: async () => {
const res = await api.get('/domains-new');
return res.data;
},
onError: (error) => {
handleError(error, { query: 'domains' });
},
retry: 3 // React Query также делает retry
});
return <div>{/* ... */}</div>;
}
Условная обработка
import { useErrorHandler } from '../hooks/useErrorHandler';
import { isCriticalError } from '../lib/api';
import api from '../lib/api';
function MyComponent() {
const { handleError } = useErrorHandler();
const loadData = async () => {
try {
const res = await api.get('/critical-data');
setData(res.data);
} catch (error) {
if (isCriticalError(error)) {
// Критичная ошибка - перенаправить
handleError(error);
navigate('/error');
} else {
// Некритичная - показать уведомление
handleError(error);
}
}
};
return <button onClick={loadData}>Загрузить</button>;
}
Batch операции
import { useErrorHandler } from '../hooks/useErrorHandler';
import api from '../lib/api';
function MyComponent() {
const { handleError, handleSuccess } = useErrorHandler();
const deleteMultiple = async (ids) => {
const errors = [];
for (const id of ids) {
try {
await api.delete(`/domains-new/${id}`);
} catch (error) {
errors.push({ id, error });
}
}
if (errors.length === 0) {
handleSuccess(`Удалено ${ids.length} элементов`);
} else {
handleError(new Error(`Не удалось удалить ${errors.length} элементов`), {
errors
});
}
};
return <button onClick={() => deleteMultiple([1, 2, 3])}>
Удалить выбранные
</button>;
}
📚 Дополнительная документация
- Полное руководство: ERROR_HANDLING_GUIDE.md
- Схемы работы: ERROR_HANDLING_FLOW.md
- Примеры кода: frontend/src/examples/ErrorHandlingExample.jsx
- Краткое резюме: ERROR_HANDLING_SUMMARY.md
🐛 Отладка
Посмотреть детали ошибки
В уведомлении кликните "Подробнее":
Детали:
{
"type": "NETWORK",
"status": null,
"message": "Не удалось подключиться к серверу",
"requestId": "abc123",
"url": "/api/domains-new",
"method": "GET",
"timestamp": "2025-10-03T15:30:45.123Z",
"action": "Проверьте подключение к интернету"
}
Консоль браузера
Все ошибки логируются в консоль:
// Открыть DevTools (F12) → Console
console.error('API Error:', {
type: 'NETWORK',
retryAttempt: 3,
maxRetries: 3,
// ...
});
Очистить кэш
// В консоли браузера
localStorage.clear();
sessionStorage.clear();
window.location.reload();
❓ FAQ
Q: Нужно ли обрабатывать каждую ошибку вручную?
A: Нет! API автоматически показывает уведомления. Используйте handleError только для локальной логики.
Q: Как отключить автоматические уведомления?
A: Используйте withErrorHandler с опцией silent: true:
withErrorHandler(fn, { silent: true })
Q: Как изменить количество retry попыток?
A: Отредактируйте frontend/src/lib/apiErrorHandler.js → getMaxRetries()
Q: Работает ли offline?
A: Частично. Приложение детектирует offline, но не сохраняет данные локально. Это можно добавить позже.
Q: Как интегрировать с Sentry?
A: См. ERROR_HANDLING_GUIDE.md → Раздел "Настройка"
✅ Чек-лист интеграции
- ErrorBoundary добавлен в App.jsx
- NetworkErrorHandler добавлен в App.jsx
- api.js обновлён с улучшенным retry
- useErrorHandler хук создан
- RetryButton компонент создан
- apiErrorHandler утилиты созданы
- Документация написана
- Примеры кода добавлены
- Линтер проверки пройдены
Статус: ✅ Готово к использованию!
🎉 Начните использовать прямо сейчас!
-
Запустите приложение:
cd backend && npm start cd frontend && npm run dev -
Импортируйте хук в любой компонент:
import { useErrorHandler } from '../hooks/useErrorHandler'; -
Используйте
withErrorHandlerилиhandleError -
Наслаждайтесь автоматической обработкой ошибок! 🚀
Вопросы? → ERROR_HANDLING_GUIDE.md
Проблемы? → Проверьте консоль браузера
Идеи? → Создайте issue или PR