Files
router-lists-ui/QUICK_START_ERROR_HANDLING.md

386 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ⚡ Быстрый старт - Обработка ошибок
## 5-минутное руководство по использованию новой системы обработки ошибок
---
## 🎯 Основные сценарии
### 1️⃣ Простая загрузка данных
```jsx
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
```jsx
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️⃣ Ручная обработка ошибок
```jsx
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`:
```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
- Показывает красивую страницу ошибки
- Кнопки восстановления
---
## 🎨 Типы уведомлений
```jsx
const { handleSuccess, handleError, handleWarning, handleInfo } = useErrorHandler();
handleSuccess('Данные сохранены'); // 🟢 Зелёное
handleError('Не удалось загрузить'); // 🔴 Красное
handleWarning('Изменения не сохранены'); // 🟡 Жёлтое
handleInfo('Проверьте обновления'); // 🔵 Синее
```
---
## 🚀 Продвинутые примеры
### React Query интеграция
```jsx
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>;
}
```
### Условная обработка
```jsx
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 операции
```jsx
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_GUIDE.md)
- **Схемы работы:** [ERROR_HANDLING_FLOW.md](./ERROR_HANDLING_FLOW.md)
- **Примеры кода:** [frontend/src/examples/ErrorHandlingExample.jsx](./frontend/src/examples/ErrorHandlingExample.jsx)
- **Краткое резюме:** [ERROR_HANDLING_SUMMARY.md](./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": "Проверьте подключение к интернету"
}
```
### Консоль браузера
Все ошибки логируются в консоль:
```javascript
// Открыть DevTools (F12) → Console
console.error('API Error:', {
type: 'NETWORK',
retryAttempt: 3,
maxRetries: 3,
// ...
});
```
### Очистить кэш
```javascript
// В консоли браузера
localStorage.clear();
sessionStorage.clear();
window.location.reload();
```
---
## ❓ FAQ
**Q: Нужно ли обрабатывать каждую ошибку вручную?**
A: Нет! API автоматически показывает уведомления. Используйте `handleError` только для локальной логики.
**Q: Как отключить автоматические уведомления?**
A: Используйте `withErrorHandler` с опцией `silent: true`:
```jsx
withErrorHandler(fn, { silent: true })
```
**Q: Как изменить количество retry попыток?**
A: Отредактируйте `frontend/src/lib/apiErrorHandler.js``getMaxRetries()`
**Q: Работает ли offline?**
A: Частично. Приложение детектирует offline, но не сохраняет данные локально. Это можно добавить позже.
**Q: Как интегрировать с Sentry?**
A: См. [ERROR_HANDLING_GUIDE.md](./ERROR_HANDLING_GUIDE.md) → Раздел "Настройка"
---
## ✅ Чек-лист интеграции
- [x] ErrorBoundary добавлен в App.jsx
- [x] NetworkErrorHandler добавлен в App.jsx
- [x] api.js обновлён с улучшенным retry
- [x] useErrorHandler хук создан
- [x] RetryButton компонент создан
- [x] apiErrorHandler утилиты созданы
- [x] Документация написана
- [x] Примеры кода добавлены
- [x] Линтер проверки пройдены
**Статус: ✅ Готово к использованию!**
---
## 🎉 Начните использовать прямо сейчас!
1. Запустите приложение:
```powershell
cd backend && npm start
cd frontend && npm run dev
```
2. Импортируйте хук в любой компонент:
```jsx
import { useErrorHandler } from '../hooks/useErrorHandler';
```
3. Используйте `withErrorHandler` или `handleError`
4. Наслаждайтесь автоматической обработкой ошибок! 🚀
---
**Вопросы?** → [ERROR_HANDLING_GUIDE.md](./ERROR_HANDLING_GUIDE.md)
**Проблемы?** → Проверьте консоль браузера
**Идеи?** → Создайте issue или PR