0
# React Server Components (RSC)
1
2
React Server Components support for tRPC with hydration helpers designed for Next.js App Router and similar frameworks that support RSC.
3
4
## Capabilities
5
6
### createHydrationHelpers
7
8
Creates utilities for prefetching data in React Server Components and hydrating the client with that data.
9
10
```typescript { .api }
11
/**
12
* Creates hydration helpers for React Server Components
13
* @param caller - Server-side router caller instance
14
* @param getQueryClient - Function that returns the QueryClient instance
15
* @returns Object with trpc proxy and HydrateClient component
16
* @note Requires @tanstack/react-query@^5.49.0
17
* @note Make sure to set serializeData/deserializeData in QueryClient for data transformers
18
*/
19
function createHydrationHelpers<TRouter extends AnyRouter>(
20
caller: Caller<TRouter>,
21
getQueryClient: () => QueryClient
22
): HydrationHelpersResult<TRouter>;
23
24
interface HydrationHelpersResult<TRouter extends AnyRouter> {
25
/** Wrapped router caller with prefetch helpers */
26
trpc: DecoratedCaller<TRouter>;
27
/** Component for hydrating client-side React Query cache */
28
HydrateClient: React.ComponentType<{ children: React.ReactNode }>;
29
}
30
31
type Caller<TRouter extends AnyRouter> = ReturnType<
32
RouterCaller<inferRouterRootTypes<TRouter>, TRouter['_def']['record']>
33
>;
34
35
type DecoratedCaller<TRouter extends AnyRouter> = {
36
// All procedures can be called directly: trpc.user.get("123")
37
// Plus prefetch methods: trpc.user.get.prefetch("123")
38
[K in keyof TRouter]: TRouter[K] extends AnyProcedure
39
? DecorateProcedure<inferRouterRootTypes<TRouter>, TRouter[K]>
40
: DecoratedCaller<TRouter[K]>;
41
};
42
43
interface DecorateProcedure<TRoot extends AnyRootTypes, TProcedure extends AnyProcedure> {
44
(input: inferProcedureInput<TProcedure>): Promise<inferProcedureOutput<TProcedure>>;
45
prefetch: (
46
input: inferProcedureInput<TProcedure>,
47
opts?: TRPCFetchQueryOptions<
48
inferTransformedProcedureOutput<TRoot, TProcedure>,
49
TRPCClientError<TRoot>
50
>
51
) => Promise<void>;
52
prefetchInfinite: (
53
input: inferProcedureInput<TProcedure>,
54
opts?: TRPCFetchInfiniteQueryOptions<
55
inferTransformedProcedureOutput<TRoot, TProcedure>,
56
TRPCClientError<TRoot>
57
>
58
) => Promise<void>;
59
}
60
```
61
62
**Usage Examples:**
63
64
```typescript
65
import { createHydrationHelpers } from "@trpc/react-query/rsc";
66
import { createCaller } from "./server/routers/app";
67
import { getQueryClient } from "./lib/query-client";
68
69
// Create the hydration helpers
70
const { trpc, HydrateClient } = createHydrationHelpers(
71
createCaller({ /* server context */ }),
72
getQueryClient
73
);
74
75
// In an RSC component
76
export default async function PostPage({ params }: { params: { id: string } }) {
77
// Direct call for immediate data
78
const post = await trpc.post.get(params.id);
79
80
// Prefetch related data for client hydration
81
await trpc.post.comments.prefetch({ postId: params.id });
82
83
return (
84
<HydrateClient>
85
<div>
86
<h1>{post.title}</h1>
87
<PostComments postId={params.id} />
88
</div>
89
</HydrateClient>
90
);
91
}
92
```
93
94
### QueryClient Configuration
95
96
For proper data transformer support, configure your QueryClient:
97
98
```typescript
99
import { QueryClient } from "@tanstack/react-query";
100
import { transformer } from "./server/transformer"; // Your data transformer
101
102
export const createQueryClient = () =>
103
new QueryClient({
104
defaultOptions: {
105
dehydrate: {
106
serializeData: transformer.serialize,
107
},
108
hydrate: {
109
deserializeData: transformer.deserialize,
110
},
111
},
112
});
113
```
114
115
### HydrateClient Component
116
117
Automatically handles hydration of prefetched data from server to client.
118
119
```typescript { .api }
120
interface HydrateClientProps {
121
children: React.ReactNode;
122
}
123
124
/**
125
* Component that wraps children with HydrationBoundary to hydrate
126
* server-prefetched data into the client QueryClient
127
*/
128
React.ComponentType<HydrateClientProps>
129
```
130
131
**Features:**
132
133
- **Server-Side Prefetching**: Use `.prefetch()` and `.prefetchInfinite()` methods on procedures
134
- **Automatic Hydration**: `HydrateClient` component handles transferring server data to client
135
- **Direct Calls**: Call procedures directly in RSC for immediate data access
136
- **Type Safety**: Full TypeScript inference from router to RSC helpers
137
- **Data Transformers**: Supports custom data transformers via QueryClient configuration
138
139
## Types
140
141
```typescript { .api }
142
interface TRPCFetchQueryOptions<TQueryFnData, TError> {
143
staleTime?: number;
144
retry?: boolean | number | ((failureCount: number, error: TError) => boolean);
145
retryDelay?: number | ((retryAttempt: number, error: TError) => number);
146
refetchOnMount?: boolean | 'always';
147
refetchOnReconnect?: boolean | 'always';
148
refetchOnWindowFocus?: boolean | 'always';
149
}
150
151
interface TRPCFetchInfiniteQueryOptions<TQueryFnData, TError>
152
extends TRPCFetchQueryOptions<TQueryFnData, TError> {
153
initialPageParam?: unknown;
154
getNextPageParam?: (lastPage: TQueryFnData, allPages: TQueryFnData[], lastPageParam: unknown, allPageParams: unknown[]) => unknown;
155
getPreviousPageParam?: (firstPage: TQueryFnData, allPages: TQueryFnData[], firstPageParam: unknown, allPageParams: unknown[]) => unknown;
156
maxPages?: number;
157
}
158
```