Server Component fetch data rồi dehydrate cache, Client Component nhận cache đã hydrate — không có flash loading.
tsx
// getQueryClient bọc trong cache() của React: mỗi request server một instance riêng
const getQueryClient = cache(() => new QueryClient())
export default async function Page() {
const queryClient = getQueryClient()
await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts })
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<PostList />
</HydrationBoundary>
)
}Client Component vẫn dùng useQuery như bình thường — nhận data từ cache đã hydrate ngay, không gọi thêm request nếu data còn fresh.
- Kết hợp Suspense để stream từng phần trang.
- Không dùng được hook React Query trong RSC (RSC chỉ là async function) — hook chỉ chạy trong Client Component.
- Prefetch trên server phần quan trọng cho lần render đầu, phần còn lại lazy load ở client.
Lưu ý: không bọc factory QueryClient trong cache() thì một QueryClient bị dùng chung cho mọi request → rò rỉ data giữa các user.