2026-04-30 19:32:10 +03:00
|
|
|
|
---
|
|
|
|
|
|
title: Клиентский GET-хук
|
|
|
|
|
|
description: Получение REST-данных в Client Components через готовые GET-хуки REST-клиента.
|
|
|
|
|
|
keywords: [rest, client components, swr, get-хук, client state]
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# Клиентский GET-хук
|
|
|
|
|
|
|
|
|
|
|
|
Клиентский GET-хук используется, когда данные зависят от состояния браузера: вкладки, фильтра, поиска, пагинации, модалки или действия пользователя.
|
|
|
|
|
|
|
|
|
|
|
|
## Когда использовать
|
|
|
|
|
|
|
|
|
|
|
|
- Запрос зависит от client state.
|
|
|
|
|
|
- Данные не обязательны для первого HTML.
|
|
|
|
|
|
- Пользователь меняет параметры запроса на клиенте.
|
|
|
|
|
|
- Нужны SWR-кеширование, дедупликация и ревалидация.
|
|
|
|
|
|
|
|
|
|
|
|
## Пример с вкладками
|
|
|
|
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
|
'use client'
|
|
|
|
|
|
|
|
|
|
|
|
import { useState } from 'react'
|
2026-05-08 19:34:39 +03:00
|
|
|
|
import { StatusEnum, useGetPetList } from 'infra/pet-store-api'
|
2026-04-30 19:32:10 +03:00
|
|
|
|
|
2026-05-08 19:34:39 +03:00
|
|
|
|
const statuses = [StatusEnum.Available, StatusEnum.Pending, StatusEnum.Sold]
|
2026-04-30 19:32:10 +03:00
|
|
|
|
|
|
|
|
|
|
export function PetTabs() {
|
2026-05-08 19:34:39 +03:00
|
|
|
|
const [status, setStatus] = useState(StatusEnum.Available)
|
|
|
|
|
|
const { data: pets, isLoading, error } = useGetPetList({ status })
|
2026-04-30 19:32:10 +03:00
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<section>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
{statuses.map((item) => (
|
|
|
|
|
|
<button key={item} type="button" onClick={() => setStatus(item)}>
|
|
|
|
|
|
{item}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{isLoading && <div>Загрузка...</div>}
|
|
|
|
|
|
{error && <div>Ошибка загрузки</div>}
|
|
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
|
{pets?.map((pet) => (
|
|
|
|
|
|
<li key={pet.id}>{pet.name}</li>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Компонент выбирает параметр `status`, но не знает про SWR-ключ и fetcher. Запрос выполняет готовый GET-хук REST-клиента.
|
|
|
|
|
|
|
|
|
|
|
|
## Если хука нет
|
|
|
|
|
|
|
|
|
|
|
|
Хук добавляется в REST-модуль сервиса:
|
|
|
|
|
|
|
|
|
|
|
|
```text
|
2026-05-08 08:21:34 +03:00
|
|
|
|
src/infra/pet-store-api/hooks/use-get-pet-list.hook.ts
|
2026-04-30 19:32:10 +03:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Не создавайте локальный `useSWR` в компоненте.
|
|
|
|
|
|
|
|
|
|
|
|
## Плохо
|
|
|
|
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
|
// Плохо — прямой вызов клиента в useEffect
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
petStoreApi.pet.findPetsByStatus({ status }).then(setPets)
|
|
|
|
|
|
}, [status])
|
|
|
|
|
|
|
|
|
|
|
|
// Плохо — useSWR в компоненте
|
|
|
|
|
|
const { data } = useSWR(
|
2026-05-08 19:34:39 +03:00
|
|
|
|
['pet-store-api', `/pet/findByStatus?status=${status}`],
|
2026-04-30 19:32:10 +03:00
|
|
|
|
() => petStoreApi.pet.findPetsByStatus({ status }),
|
|
|
|
|
|
)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Такой код теряет единое место для ключей, дублирует fetcher и разносит инфраструктурные детали по UI.
|
|
|
|
|
|
|
|
|
|
|
|
## Когда выбрать другую стратегию
|
|
|
|
|
|
|
|
|
|
|
|
- Данные нужны до первого HTML — [Серверный await](./server-await.md).
|
|
|
|
|
|
- Клиентский хук должен получить начальные данные сразу — [Начальные данные для клиентских хуков](./client-hooks-initial-data.md).
|
|
|
|
|
|
- Нужно вычислить бизнес-состояние — [Business-композиция](./business-composition.md).
|