125 lines
8.4 KiB
Markdown
125 lines
8.4 KiB
Markdown
# Хуки API (React Hooks)
|
||
|
||
> В проекте для работы с API-хуками используется только React и библиотека SWR для получения данных (GET-запросы).
|
||
> В этом разделе собраны основные правила и рекомендации по созданию и оформлению хуков для работы с API. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, переиспользуемость и единый стиль работы с API-хуками в проекте.
|
||
|
||
## Описание и назначение API-хуков
|
||
|
||
API-хуки предназначены для получения данных с сервера (GET-запросы) и используются в компонентах или других хуках.
|
||
В проекте для этого применяется библиотека SWR, которая обеспечивает кэширование, автоматическое обновление и удобную работу с асинхронными запросами.
|
||
|
||
**Fetcher** — это функция, которую использует SWR для выполнения запроса к API. В проекте fetcher обычно экспортируется из файла клиента (например, `backendFetcher` из `shared/api/backend/client.ts`) и инкапсулирует логику обращения к конкретному API-клиенту.
|
||
|
||
**API-клиент** — это отдельный модуль (папка), отвечающий за взаимодействие с конкретным внешним или внутренним API.
|
||
API-клиент включает:
|
||
- инициализацию экземпляра HTTP-клиента (например, Axios),
|
||
- настройку базового URL, интерцепторов и общих обработчиков ошибок,
|
||
- организацию всех сущностей и методов для работы с этим API (например, users, auth, orders и т.д.),
|
||
- экспорт всех функций, типов и fetcher через индексные файлы.
|
||
|
||
Каждый API-клиент размещается в папке `src/shared/api/<client-name>/` и имеет собственную структуру согласно архитектуре проекта.
|
||
|
||
## Структура
|
||
- Каждый API-хук размещается в отдельном файле с именем `use-<method-name>.hook-api.ts` в папке `hooks/api/<client-name>/` на своём уровне абстракции согласно архитектуре проекта.
|
||
- Имя хука — в стиле camelCase с префиксом `use` (например, `useGetUser`).
|
||
- Для сложных возвращаемых структур используйте отдельные типы или интерфейсы, размещая их в папке `types/` на своём уровне абстракции.
|
||
|
||
## Именование
|
||
- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок):
|
||
- Файл хука — `use-<method-name>.hook-api.ts` (kebab-case).
|
||
- Имя хука — camelCase с префиксом `use`.
|
||
|
||
## Требования
|
||
- Хук должен быть строго типизирован: все параметры, возвращаемые значения и внутренние переменные должны иметь явные типы.
|
||
- Для получения данных используйте только SWR.
|
||
- Не дублируйте логику между хуками — общие части выносите в shared.
|
||
- Не используйте side-effects вне useEffect/useLayoutEffect.
|
||
|
||
## Типизация
|
||
- Всегда явно указывайте типы для всех параметров, возвращаемых значений и состояния внутри хука.
|
||
- Придерживайтесь [общих правил типизации проекта](#общие-правила-типизации).
|
||
- Не используйте неявное приведение типов и не полагайтесь на автоматический вывод, если это может снизить читаемость или безопасность.
|
||
|
||
## Документирование
|
||
- Документируйте только назначение хука (описание), строго по [правилам документирования кода](#правило-для-документирования-кода).
|
||
|
||
## Экспорт
|
||
- Экспортируйте хук только именованным экспортом через `index.ts` слоя/компонента.
|
||
|
||
## Пример API хука
|
||
|
||
```ts
|
||
// use-get-me.hook-api.ts
|
||
import useSWR from 'swr';
|
||
import { backendFetcher } from 'shared/api/backend/client';
|
||
import { UserDto } from 'shared/api/backend/entities/users/get-me.api';
|
||
|
||
/**
|
||
* Хук для получения информации о текущем пользователе.
|
||
*/
|
||
export const useGetMe = () => {
|
||
const { data, error, isLoading } = useSWR<UserDto>('/users/me', backendFetcher);
|
||
|
||
return {
|
||
data,
|
||
error,
|
||
isLoading,
|
||
};
|
||
};
|
||
```
|
||
|
||
### Пример использования хука в компоненте
|
||
|
||
```tsx
|
||
import React from 'react';
|
||
import { useGetMe } from 'shared/hooks/api/backend/use-get-me.hook-api';
|
||
|
||
export const UserInfo: React.FC = () => {
|
||
const { data, error, isLoading } = useGetMe();
|
||
|
||
if (isLoading) {
|
||
return <div>Загрузка...</div>;
|
||
}
|
||
|
||
if (error) {
|
||
return <div>Ошибка загрузки данных</div>;
|
||
}
|
||
|
||
if (!data) {
|
||
return <div>Нет данных о пользователе</div>;
|
||
}
|
||
|
||
return (
|
||
<div>
|
||
<div>Имя: {data.name}</div>
|
||
<div>Email: {data.email}</div>
|
||
</div>
|
||
);
|
||
};
|
||
```
|
||
|
||
## Чек-лист для создания API-хука
|
||
|
||
- [ ] Для каждого GET-запроса создан отдельный хук.
|
||
- [ ] Хук размещён в `hooks/api/<client-name>/use-<method-name>.hook-api.ts` на своём уровне абстракции согласно архитектуре проекта.
|
||
- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок).
|
||
- [ ] Используется SWR для получения данных.
|
||
- [ ] Все параметры, возвращаемые значения и внутренние переменные строго типизированы.
|
||
- [ ] Нет дублирования логики между хуками.
|
||
- [ ] Не используются side-effects вне useEffect/useLayoutEffect.
|
||
- [ ] Документировано только назначение хука (см. [правила документирования кода](#правило-для-документирования-кода)).
|
||
- [ ] Нет неиспользуемого или невалидного кода.
|
||
- [ ] Экспорт только именованный через индексный файл.
|
||
|
||
---
|
||
|
||
## Чек-лист для использования API-хука
|
||
|
||
- [ ] Импортируется только нужный хук через публичные экспорты (`index.ts`).
|
||
- [ ] Использование хука строго по назначению (только для получения данных).
|
||
- [ ] Если требуется получить данные через GET-запрос в компоненте — обязательно используется соответствующий API-хук.
|
||
**Запрещено вызывать GET-методы API напрямую в компонентах, только через хуки.**
|
||
- [ ] Обработка состояний загрузки, ошибки и данных реализована корректно.
|
||
- [ ] Не происходит дублирования логики, связанной с получением данных.
|
||
- [ ] Нет неиспользуемого или невалидного кода.
|