Prefetch on hover (client) hoặc trong Server Component (server) để data sẵn sàng trước khi user cần — loại bỏ loading state hoàn toàn.
- Prefetching là kỹ thuật fetch data trước khi user cần, giúp loại bỏ loading state.
- Client-side pattern: prefetch on hover để khi user click vào link thì data đã sẵn sàng —
const handleMouseEnter = () => queryClient.prefetchQuery({ queryKey: ['post', id], queryFn: () => fetchPost(id), staleTime: 30_000 }). - Server-side với Next.js App Router:
const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts }); const dehydratedState = dehydrate(queryClient); return <HydrationBoundary state={dehydratedState}><PostList /></HydrationBoundary>— client nhận data đã fetch sẵn, không có loading flash.prefetchInfiniteQuerycho infinite scroll pages: pre-load trang đầu tiên trên server, user thấy content ngay. - Prefetch trong route handler (Next.js): đặt prefetch logic trong layout.tsx để data sẵn sàng trước khi page.tsx render.
- Lưu ý: prefetchQuery không throw error (khác fetchQuery), query silently fails — luôn check error state ở component level.
Prefetch on hover (client-side) or in Server Components (server-side) so data is ready before the user needs it — eliminates loading states entirely.
- Prefetching fetches data before the user needs it, eliminating loading states.
- Client-side pattern: prefetch on hover so data is ready when the user clicks —
const handleMouseEnter = () => queryClient.prefetchQuery({ queryKey: ['post', id], queryFn: () => fetchPost(id), staleTime: 30_000 }). - Server-side with Next.js App Router:
const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts }); const dehydratedState = dehydrate(queryClient); return <HydrationBoundary state={dehydratedState}><PostList /></HydrationBoundary>— the client receives already-fetched data with no loading flash.prefetchInfiniteQueryfor infinite scroll: pre-load the first page on the server so content appears immediately. - Prefetch in route handlers (Next.js): put prefetch logic in layout.tsx so data is ready before page.tsx renders.
Pitfall: prefetchQuery does not throw errors (unlike fetchQuery) — queries silently fail; always check error state at the component level.