- Добавлена документация SLM-архитектуры, базовых правил и прикладных разделов - Добавлены разделы: стили, SVG-спрайты, шаблоны генерации, PostCSS, REST, Realtime - Удалены устаревшие файлы (спрайты, скрипты, стили из app/)
110 lines
4.7 KiB
Markdown
110 lines
4.7 KiB
Markdown
---
|
||
title: Начальные данные для клиентских хуков
|
||
description: Как дать клиентским GET-хукам начальные REST-данные.
|
||
keywords: [rest, swr, fallback, initial data, client hooks, unstable_serialize, isr, ssr]
|
||
---
|
||
|
||
# Начальные данные для клиентских хуков
|
||
|
||
Как дать клиентским GET-хукам начальные REST-данные.
|
||
|
||
Эта стратегия используется, когда данные должны быть запущены на сервере, но потребляться на клиенте через GET-хуки REST-клиента.
|
||
|
||
Технически это делается через `SWRConfig fallback`: сервер передаёт промис в fallback, а клиентский хук использует тот же SWR-ключ.
|
||
|
||
## Когда использовать
|
||
|
||
- Внутри страницы есть Client Components с GET-хуками.
|
||
- Нужно начать загрузку данных на сервере раньше.
|
||
- Клиентский компонент должен остаться обычным потребителем `useGetPetList(...)`.
|
||
- Не нужно писать отдельный prop-drilling для начальных данных.
|
||
|
||
## Рендер страницы
|
||
|
||
Перед этой стратегией сначала определите рендер маршрута. Серверный preload для `fallback` подчиняется тем же правилам, что и любой серверный запрос в `page.tsx` или `layout.tsx`.
|
||
|
||
Если данные общие и могут обновляться по интервалу, сохраняйте static/ISR. Если preload зависит от cookie, headers, `searchParams`, `no-store` или персональных данных пользователя, маршрут становится dynamic/SSR.
|
||
|
||
`SWRConfig fallback` не должен быть причиной отключать ISR на всякий случай. Он только передаёт клиентскому GET-хуку данные, которые уже были запущены на сервере.
|
||
|
||
## Ключ хука
|
||
|
||
```ts
|
||
// src/infrastructure/pet-store-api/hooks/use-get-pet-list.hook.ts
|
||
export const getPetListKey = (status: PetStatus) =>
|
||
['pet-store-api', 'pet', 'list', status] as const
|
||
```
|
||
|
||
Ключ экспортируется из REST-модуля, потому что он нужен и GET-хуку, и серверному `SWRConfig fallback`.
|
||
|
||
## Пример layout
|
||
|
||
```tsx
|
||
// src/app/(routes)/pets/layout.tsx
|
||
import type { ReactNode } from 'react'
|
||
import { SWRConfig, unstable_serialize } from 'swr'
|
||
import {
|
||
getPetListKey,
|
||
petStoreApi,
|
||
} from 'infrastructure/pet-store-api'
|
||
|
||
type PetsLayoutProps = {
|
||
children: ReactNode
|
||
}
|
||
|
||
export default async function PetsLayout({ children }: PetsLayoutProps) {
|
||
const availablePetsPromise = petStoreApi.pet.findPetsByStatus({
|
||
status: 'available',
|
||
})
|
||
|
||
return (
|
||
<SWRConfig
|
||
value={{
|
||
fallback: {
|
||
[unstable_serialize(getPetListKey('available'))]: availablePetsPromise,
|
||
},
|
||
}}
|
||
>
|
||
{children}
|
||
</SWRConfig>
|
||
)
|
||
}
|
||
```
|
||
|
||
Если GET-хук использует array-key, ключ для `fallback` сериализуется через `unstable_serialize`.
|
||
|
||
## Клиентский компонент
|
||
|
||
```tsx
|
||
'use client'
|
||
|
||
import { useGetPetList } from 'infrastructure/pet-store-api'
|
||
|
||
export function PetList() {
|
||
const { data: pets, isLoading } = useGetPetList('available')
|
||
|
||
if (isLoading) return <div>Загрузка...</div>
|
||
|
||
return (
|
||
<ul>
|
||
{pets?.map((pet) => (
|
||
<li key={pet.id}>{pet.name}</li>
|
||
))}
|
||
</ul>
|
||
)
|
||
}
|
||
```
|
||
|
||
Компонент не знает, что данные были запущены на сервере. Он использует обычный GET-хук REST-клиента.
|
||
|
||
## Что важно
|
||
|
||
- Ключ `fallback` должен совпадать с ключом GET-хука.
|
||
- Серверный код вызывает метод клиента, а не GET-хук.
|
||
- Клиентский компонент вызывает GET-хук, а не `useSWR` напрямую.
|
||
- Эта стратегия не означает ручную работу с кешем в компонентах.
|
||
|
||
## Когда не использовать
|
||
|
||
Если данные нужны только серверному компоненту, используйте [Серверный await](./server-await.md). Если данные зависят от состояния браузера, используйте [Клиентский GET-хук](./client-get-hook.md).
|