Server Rendering
The common strategy to efficiently and optimally do server side rendering, as well as prevent request waterfalls on the client, is to do prefetching on the server, then pass a dehydrated form of the query cache from the server to the client.
In these scenarios, the React Query code will not run inside a provider, so we need to initialize the QueryClient
manually and pass it to ts-rest.
Therefore, instead of using tsr.useQueryClient()
as you usually would in your components, use tsr.initQueryClient(queryClient)
to pass your created QueryClient
to ts-rest.
See the @tanstack/react-query
Server Rendering Guide for an in-depth guide on how to properly do server side rendering.
Examples
Next.js Pages Router
// pages/posts.tsx
import { dehydrate, QueryClient } from '@tanstack/react-query';
import { tsr } from './tsr';
export async function getServerSideProps() {
const tsrQueryClient = tsr.initQueryClient(new QueryClient());
await tsrQueryClient.getPosts.prefetchQuery({ queryKey: ['POSTS'] });
return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
React Server Components
// app/posts/page.tsx
import { dehydrate, HydrationBoundary, QueryClient} from '@tanstack/react-query';
import { tsr } from './tsr';
export default async function PostsPage() {
const tsrQueryClient = tsr.initQueryClient(new QueryClient()); // <-- or pass a QueryClient from anywhere depending on your needs
await tsrQueryClient.getPosts.prefetchQuery({ queryKey: ['POSTS'] });
return (
<HydrationBoundary state={dehydrate(tsrQueryClient)}>
<Posts />
</HydrationBoundary>
);
}