Перейти к содержимому

10. Query: prefetching и SSR

Prefetching — загрузка данных заранее, до того как они понадобятся. Это устраняет задержку загрузки при навигации: данные уже в кэше, компонент рендерится мгновенно.

const queryClient = useQueryClient()
// Предзагрузка данных при hover на ссылку
const handleMouseEnter = () => {
queryClient.prefetchQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
staleTime: 1000 * 60, // Не предзагружать если данные свежие
})
}

При hover пользователя на ссылку — данные уже загружаются. При клике — мгновенный переход.

Многие роутеры поддерживают prefetch на уровне маршрутизации:

// TanStack Router loader
export const Route = createFileRoute('/users/$userId')({
loader: ({ context: { queryClient }, params }) =>
queryClient.ensureQueryData({
queryKey: ['user', params.userId],
queryFn: () => fetchUser(params.userId),
}),
})

ensureQueryData — как prefetchQuery, но возвращает данные из кэша если они свежие.

Для серверного рендеринга нужно передать данные из сервера в клиент:

// Сервер (Next.js, Remix, TanStack Start)
export async function getServerSideProps() {
const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryKey: ['users'],
queryFn: getUsers,
})
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
// Клиент
function App({ dehydratedState }) {
return (
<HydrationBoundary state={dehydratedState}>
<Users />
</HydrationBoundary>
)
}

Позволяет передать начальные данные напрямую в запрос:

const { data } = useQuery({
queryKey: ['user', userId],
queryFn: fetchUser,
initialData: userFromSSR, // Данные из SSR
initialDataUpdatedAt: Date.now(), // Когда данные были получены
})

initialData vs placeholderData:

  • initialData — реальные данные, кэшируются, влияют на staleTime
  • placeholderData — временные данные, не кэшируются, заменяются при загрузке
useQuery({
queryKey: ['user', userId],
queryFn: fetchUser,
placeholderData: (previousData) => previousData, // Показываем старые данные при смене userId
})

Особенно полезно при пагинации — показываем данные текущей страницы пока грузится следующая.