Transfer prefetched query data from server to client
Server-rendered routes
TanStack · Component
HydrationBoundary places previously dehydrated query state into a QueryClient for a rendered subtree. It merges overlapping data by freshness and always renders its children.
HydrationBoundary accepts dehydrated query state and makes it available through the relevant QueryClient while always rendering its children. New queries are incorporated during render; existing cached queries are updated after commit only when the dehydrated data is newer.
<HydrationBoundary state={dehydratedState}>{children}</HydrationBoundary>| Name | Type | Description |
|---|---|---|
__namedParameters | HydrationBoundaryProps | Props containing the dehydrated state and the children to render; the API also accepts optional hydration options and a custom QueryClient. |
Element: the supplied children, rendered unconditionally.
import { HydrationBoundary, dehydrate, QueryClient } from '@tanstack/react-query'
export default async function Page() {
const queryClient = new QueryClient()
await queryClient.prefetchQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
})
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<Posts />
</HydrationBoundary>
)
}Prefetches server data, serializes the client cache, and provides it to the rendered subtree.
Server-rendered routes
Streaming or concurrent React applications
Client navigation with an existing cache
It receives a dehydrated state, typically produced with dehydrate, and hydrates that state into the query client used by the component tree. Children render unconditionally rather than waiting for hydration.
Follow-up: What differs for queries already cached on the client? Only newer dehydrated data is applied, and it is applied in an effect after commit rather than during render.
It hydrates queries but not mutations. Mutation hydration requires the lower-level hydrate API or the persistQueryClient plugin.
Follow-up: Why might a mutation not be visible after rendering a HydrationBoundary? Because the boundary deliberately handles query state only; mutation state must be restored separately.
When a query is absent from the client cache, its dehydrated state is hydrated during render. When it already exists, only fresher dehydrated data is applied after commit.
Follow-up: What user-visible effect can this timing cause? A child may briefly render with the existing cache value before the fresher dehydrated value arrives.
dehydratehydrateQueryClientQueryClientProviderHydrateOptionsDehydratedState