@apollo/client 4.2.0-alpha.1 → 4.2.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/__cjs/core/ApolloClient.cjs +25 -12
  3. package/__cjs/core/ApolloClient.cjs.map +1 -1
  4. package/__cjs/core/ApolloClient.d.cts +305 -146
  5. package/__cjs/core/QueryManager.cjs.map +1 -1
  6. package/__cjs/core/defaultOptions.cjs +3 -0
  7. package/__cjs/core/defaultOptions.cjs.map +1 -0
  8. package/__cjs/core/defaultOptions.d.cts +90 -0
  9. package/__cjs/core/index.cjs.map +1 -1
  10. package/__cjs/core/index.d.cts +2 -1
  11. package/__cjs/link/ws/index.cjs +9 -1
  12. package/__cjs/link/ws/index.cjs.map +1 -1
  13. package/__cjs/link/ws/index.d.cts +1 -1
  14. package/__cjs/react/hooks/useBackgroundQuery.cjs +3 -3
  15. package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
  16. package/__cjs/react/hooks/useBackgroundQuery.d.cts +1598 -765
  17. package/__cjs/react/hooks/useLazyQuery.cjs +3 -5
  18. package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
  19. package/__cjs/react/hooks/useLazyQuery.d.cts +369 -115
  20. package/__cjs/react/hooks/useLoadableQuery.cjs +8 -4
  21. package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
  22. package/__cjs/react/hooks/useLoadableQuery.d.cts +507 -192
  23. package/__cjs/react/hooks/useMutation.cjs +5 -48
  24. package/__cjs/react/hooks/useMutation.cjs.map +1 -1
  25. package/__cjs/react/hooks/useMutation.d.cts +239 -130
  26. package/__cjs/react/hooks/useQuery.cjs +5 -5
  27. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  28. package/__cjs/react/hooks/useQuery.d.cts +636 -276
  29. package/__cjs/react/hooks/useSubscription.cjs +1 -1
  30. package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
  31. package/__cjs/react/hooks/useSubscription.d.cts +2 -2
  32. package/__cjs/react/hooks/useSuspenseQuery.cjs +3 -3
  33. package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
  34. package/__cjs/react/hooks/useSuspenseQuery.d.cts +799 -399
  35. package/__cjs/react/internal/cache/getSuspenseCache.cjs.map +1 -1
  36. package/__cjs/react/internal/cache/getSuspenseCache.d.cts +7 -0
  37. package/__cjs/utilities/internal/LazyType.cjs +3 -0
  38. package/__cjs/utilities/internal/LazyType.cjs.map +1 -0
  39. package/__cjs/utilities/internal/LazyType.d.cts +10 -0
  40. package/__cjs/utilities/internal/index.cjs.map +1 -1
  41. package/__cjs/utilities/internal/index.d.cts +3 -0
  42. package/__cjs/utilities/internal/types/OptionWithFallback.cjs +3 -0
  43. package/__cjs/utilities/internal/types/OptionWithFallback.cjs.map +1 -0
  44. package/__cjs/utilities/internal/types/OptionWithFallback.d.cts +5 -0
  45. package/__cjs/utilities/internal/types/SignatureStyle.cjs +3 -0
  46. package/__cjs/utilities/internal/types/SignatureStyle.cjs.map +1 -0
  47. package/__cjs/utilities/internal/types/SignatureStyle.d.cts +24 -0
  48. package/__cjs/version.cjs +1 -1
  49. package/core/ApolloClient.d.ts +305 -146
  50. package/core/ApolloClient.js +25 -12
  51. package/core/ApolloClient.js.map +1 -1
  52. package/core/QueryManager.js.map +1 -1
  53. package/core/defaultOptions.d.ts +90 -0
  54. package/core/defaultOptions.js +2 -0
  55. package/core/defaultOptions.js.map +1 -0
  56. package/core/index.d.ts +2 -1
  57. package/core/index.js.map +1 -1
  58. package/link/ws/index.d.ts +1 -1
  59. package/link/ws/index.js +9 -1
  60. package/link/ws/index.js.map +1 -1
  61. package/package.json +3 -7
  62. package/react/hooks/useBackgroundQuery.d.ts +1598 -765
  63. package/react/hooks/useBackgroundQuery.js +2 -2
  64. package/react/hooks/useBackgroundQuery.js.map +1 -1
  65. package/react/hooks/useLazyQuery.d.ts +369 -115
  66. package/react/hooks/useLazyQuery.js +2 -4
  67. package/react/hooks/useLazyQuery.js.map +1 -1
  68. package/react/hooks/useLoadableQuery.d.ts +507 -192
  69. package/react/hooks/useLoadableQuery.js +7 -3
  70. package/react/hooks/useLoadableQuery.js.map +1 -1
  71. package/react/hooks/useMutation.d.ts +239 -130
  72. package/react/hooks/useMutation.js +5 -48
  73. package/react/hooks/useMutation.js.map +1 -1
  74. package/react/hooks/useQuery.d.ts +636 -276
  75. package/react/hooks/useQuery.js +2 -2
  76. package/react/hooks/useQuery.js.map +1 -1
  77. package/react/hooks/useSubscription.d.ts +2 -2
  78. package/react/hooks/useSubscription.js +1 -1
  79. package/react/hooks/useSubscription.js.map +1 -1
  80. package/react/hooks/useSuspenseQuery.d.ts +799 -399
  81. package/react/hooks/useSuspenseQuery.js +2 -2
  82. package/react/hooks/useSuspenseQuery.js.map +1 -1
  83. package/react/hooks-compiled/useBackgroundQuery.d.ts +1598 -765
  84. package/react/hooks-compiled/useBackgroundQuery.js +2 -2
  85. package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
  86. package/react/hooks-compiled/useLazyQuery.d.ts +369 -115
  87. package/react/hooks-compiled/useLazyQuery.js +2 -4
  88. package/react/hooks-compiled/useLazyQuery.js.map +1 -1
  89. package/react/hooks-compiled/useLoadableQuery.d.ts +507 -192
  90. package/react/hooks-compiled/useLoadableQuery.js +2 -2
  91. package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
  92. package/react/hooks-compiled/useMutation.d.ts +239 -130
  93. package/react/hooks-compiled/useMutation.js +4 -47
  94. package/react/hooks-compiled/useMutation.js.map +1 -1
  95. package/react/hooks-compiled/useQuery.d.ts +636 -276
  96. package/react/hooks-compiled/useQuery.js +2 -2
  97. package/react/hooks-compiled/useQuery.js.map +1 -1
  98. package/react/hooks-compiled/useSubscription.d.ts +2 -2
  99. package/react/hooks-compiled/useSubscription.js +1 -1
  100. package/react/hooks-compiled/useSubscription.js.map +1 -1
  101. package/react/hooks-compiled/useSuspenseQuery.d.ts +799 -399
  102. package/react/hooks-compiled/useSuspenseQuery.js +2 -2
  103. package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
  104. package/react/internal/cache/getSuspenseCache.d.ts +7 -0
  105. package/react/internal/cache/getSuspenseCache.js.map +1 -1
  106. package/skills/apollo-client/SKILL.md +168 -0
  107. package/skills/apollo-client/references/caching.md +560 -0
  108. package/skills/apollo-client/references/error-handling.md +350 -0
  109. package/skills/apollo-client/references/fragments.md +804 -0
  110. package/skills/apollo-client/references/integration-client.md +336 -0
  111. package/skills/apollo-client/references/integration-nextjs.md +325 -0
  112. package/skills/apollo-client/references/integration-react-router.md +256 -0
  113. package/skills/apollo-client/references/integration-tanstack-start.md +378 -0
  114. package/skills/apollo-client/references/mutations.md +549 -0
  115. package/skills/apollo-client/references/queries.md +416 -0
  116. package/skills/apollo-client/references/state-management.md +428 -0
  117. package/skills/apollo-client/references/suspense-hooks.md +773 -0
  118. package/skills/apollo-client/references/troubleshooting.md +487 -0
  119. package/skills/apollo-client/references/typescript-codegen.md +133 -0
  120. package/utilities/internal/LazyType.d.ts +10 -0
  121. package/utilities/internal/LazyType.js +2 -0
  122. package/utilities/internal/LazyType.js.map +1 -0
  123. package/utilities/internal/index.d.ts +3 -0
  124. package/utilities/internal/index.js.map +1 -1
  125. package/utilities/internal/types/OptionWithFallback.d.ts +5 -0
  126. package/utilities/internal/types/OptionWithFallback.js +2 -0
  127. package/utilities/internal/types/OptionWithFallback.js.map +1 -0
  128. package/utilities/internal/types/SignatureStyle.d.ts +24 -0
  129. package/utilities/internal/types/SignatureStyle.js +2 -0
  130. package/utilities/internal/types/SignatureStyle.js.map +1 -0
  131. package/version.js +1 -1
@@ -0,0 +1,336 @@
1
+ # Apollo Client Integration for Client-Side Apps
2
+
3
+ This guide covers setting up Apollo Client in client-side React applications without server-side rendering (SSR). This includes applications using Vite, Parcel, Create React App, or other bundlers that don't implement SSR.
4
+
5
+ For applications with SSR, use one of the framework-specific integration guides instead:
6
+
7
+ - [Next.js App Router](integration-nextjs.md)
8
+ - [React Router Framework Mode](integration-react-router.md)
9
+ - [TanStack Start](integration-tanstack-start.md)
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @apollo/client graphql rxjs
15
+ ```
16
+
17
+ ## TypeScript Code Generation (optional but recommended)
18
+
19
+ For type-safe GraphQL operations with TypeScript, see the [TypeScript Code Generation guide](typescript-codegen.md).
20
+
21
+ ## Setup Steps
22
+
23
+ ### Step 1: Create Client
24
+
25
+ ```typescript
26
+ import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
27
+
28
+ // Recommended: Use HttpOnly cookies for authentication
29
+ const httpLink = new HttpLink({
30
+ uri: "https://your-graphql-endpoint.com/graphql",
31
+ credentials: "include", // Sends cookies with requests (secure when using HttpOnly cookies)
32
+ });
33
+
34
+ const client = new ApolloClient({
35
+ link: httpLink,
36
+ cache: new InMemoryCache(),
37
+ });
38
+ ```
39
+
40
+ If you need manual token management (less secure, only when HttpOnly cookies aren't available):
41
+
42
+ ```typescript
43
+ import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
44
+ import { SetContextLink } from "@apollo/client/link/context";
45
+
46
+ const httpLink = new HttpLink({
47
+ uri: "https://your-graphql-endpoint.com/graphql",
48
+ });
49
+
50
+ const authLink = new SetContextLink(({ headers }) => {
51
+ const token = localStorage.getItem("token");
52
+ return {
53
+ headers: {
54
+ ...headers,
55
+ authorization: token ? `Bearer ${token}` : "",
56
+ },
57
+ };
58
+ });
59
+
60
+ const client = new ApolloClient({
61
+ link: authLink.concat(httpLink),
62
+ cache: new InMemoryCache(),
63
+ });
64
+ ```
65
+
66
+ ### Step 2: Setup Provider
67
+
68
+ ```tsx
69
+ import { ApolloProvider } from "@apollo/client";
70
+ import App from "./App";
71
+
72
+ function Root() {
73
+ return (
74
+ <ApolloProvider client={client}>
75
+ <App />
76
+ </ApolloProvider>
77
+ );
78
+ }
79
+ ```
80
+
81
+ ### Step 3: Execute Query
82
+
83
+ ```tsx
84
+ import { gql } from "@apollo/client";
85
+ import { useQuery } from "@apollo/client/react";
86
+
87
+ const GET_USERS = gql`
88
+ query GetUsers {
89
+ users {
90
+ id
91
+ name
92
+ email
93
+ }
94
+ }
95
+ `;
96
+
97
+ function UserList() {
98
+ const { loading, error, data, dataState } = useQuery(GET_USERS);
99
+
100
+ if (loading) return <p>Loading...</p>;
101
+ if (error) return <p>Error: {error.message}</p>;
102
+
103
+ // TypeScript note: for stricter type narrowing, you can also check `dataState === "complete"` before accessing data
104
+ return (
105
+ <ul>{data?.users.map((user) => <li key={user.id}>{user.name}</li>)}</ul>
106
+ );
107
+ }
108
+ ```
109
+
110
+ ## Basic Query Usage
111
+
112
+ ### Using Variables
113
+
114
+ ```tsx
115
+ const GET_USER = gql`
116
+ query GetUser($id: ID!) {
117
+ user(id: $id) {
118
+ id
119
+ name
120
+ email
121
+ }
122
+ }
123
+ `;
124
+
125
+ function UserProfile({ userId }: { userId: string }) {
126
+ const { loading, error, data, dataState } = useQuery(GET_USER, {
127
+ variables: { id: userId },
128
+ });
129
+
130
+ if (loading) return <p>Loading...</p>;
131
+ if (error) return <p>Error: {error.message}</p>;
132
+
133
+ // TypeScript note: for stricter type narrowing, you can also check `dataState === "complete"` before accessing data
134
+ return <div>{data?.user.name}</div>;
135
+ }
136
+ ```
137
+
138
+ > **Note for TypeScript users**: Use [`dataState`](https://www.apollographql.com/docs/react/data/typescript#type-narrowing-data-with-datastate) for more robust type safety and better type narrowing in Apollo Client 4.x.
139
+
140
+ ### TypeScript Integration
141
+
142
+ For complete examples with loading, error handling, and `dataState` for type narrowing, see [Basic Query Usage](#basic-query-usage) above.
143
+
144
+ #### Usage with Generated Types
145
+
146
+ For type-safe operations with code generation, see the [TypeScript Code Generation guide](typescript-codegen.md).
147
+
148
+ Quick example:
149
+
150
+ ```typescript
151
+ import { gql } from "@apollo/client";
152
+ import { useQuery } from "@apollo/client/react";
153
+ import { GetUserDocument } from "./queries.generated";
154
+
155
+ // Define your query with the if (false) pattern for code generation
156
+ if (false) {
157
+ gql`
158
+ query GetUser($id: ID!) {
159
+ user(id: $id) {
160
+ id
161
+ name
162
+ email
163
+ }
164
+ }
165
+ `;
166
+ }
167
+
168
+ function UserProfile({ userId }: { userId: string }) {
169
+ // Types are automatically inferred from GetUserDocument
170
+ const { data } = useQuery(GetUserDocument, {
171
+ variables: { id: userId },
172
+ });
173
+
174
+ return <div>{data.user.name}</div>;
175
+ }
176
+ ```
177
+
178
+ #### Usage with Manual Type Annotations
179
+
180
+ If not using code generation, define types alongside your queries using `TypedDocumentNode`:
181
+
182
+ ```typescript
183
+ import { gql, TypedDocumentNode } from "@apollo/client";
184
+ import { useQuery } from "@apollo/client/react";
185
+
186
+ interface GetUserData {
187
+ user: {
188
+ id: string;
189
+ name: string;
190
+ email: string;
191
+ };
192
+ }
193
+
194
+ interface GetUserVariables {
195
+ id: string;
196
+ }
197
+
198
+ // Types should always be defined via TypedDocumentNode alongside your queries/mutations, not at the useQuery/useMutation call site
199
+ const GET_USER: TypedDocumentNode<GetUserData, GetUserVariables> = gql`
200
+ query GetUser($id: ID!) {
201
+ user(id: $id) {
202
+ id
203
+ name
204
+ email
205
+ }
206
+ }
207
+ `;
208
+
209
+ function UserProfile({ userId }: { userId: string }) {
210
+ const { data } = useQuery(GET_USER, {
211
+ variables: { id: userId },
212
+ });
213
+
214
+ // data.user is automatically typed from GET_USER
215
+ return <div>{data.user.name}</div>;
216
+ }
217
+ ```
218
+
219
+ ## Basic Mutation Usage
220
+
221
+ ```tsx
222
+ import { gql, TypedDocumentNode } from "@apollo/client";
223
+ import { useMutation } from "@apollo/client/react";
224
+
225
+ interface CreateUserMutation {
226
+ createUser: {
227
+ id: string;
228
+ name: string;
229
+ email: string;
230
+ };
231
+ }
232
+
233
+ interface CreateUserMutationVariables {
234
+ input: {
235
+ name: string;
236
+ email: string;
237
+ };
238
+ }
239
+
240
+ const CREATE_USER: TypedDocumentNode<
241
+ CreateUserMutation,
242
+ CreateUserMutationVariables
243
+ > = gql`
244
+ mutation CreateUser($input: CreateUserInput!) {
245
+ createUser(input: $input) {
246
+ id
247
+ name
248
+ email
249
+ }
250
+ }
251
+ `;
252
+
253
+ function CreateUserForm() {
254
+ const [createUser, { loading, error }] = useMutation(CREATE_USER);
255
+
256
+ const handleSubmit = async (formData: FormData) => {
257
+ const { data } = await createUser({
258
+ variables: {
259
+ input: {
260
+ name: formData.get("name") as string,
261
+ email: formData.get("email") as string,
262
+ },
263
+ },
264
+ });
265
+ if (data) {
266
+ console.log("Created user:", data.createUser);
267
+ }
268
+ };
269
+
270
+ return (
271
+ <form
272
+ onSubmit={(e) => {
273
+ e.preventDefault();
274
+ handleSubmit(new FormData(e.currentTarget));
275
+ }}
276
+ >
277
+ <input name="name" placeholder="Name" />
278
+ <input name="email" placeholder="Email" />
279
+ <button type="submit" disabled={loading}>
280
+ {loading ? "Creating..." : "Create User"}
281
+ </button>
282
+ {error && <p>Error: {error.message}</p>}
283
+ </form>
284
+ );
285
+ }
286
+ ```
287
+
288
+ ## Client Configuration Options
289
+
290
+ ```typescript
291
+ const client = new ApolloClient({
292
+ // Required: The cache implementation
293
+ cache: new InMemoryCache({
294
+ typePolicies: {
295
+ Query: {
296
+ fields: {
297
+ // Field-level cache configuration
298
+ },
299
+ },
300
+ },
301
+ }),
302
+
303
+ // Network layer
304
+ link: new HttpLink({ uri: "/graphql" }),
305
+
306
+ // Avoid defaultOptions if possible as they break TypeScript expectations.
307
+ // Configure options per-query/mutation instead for better type safety.
308
+ // defaultOptions: {
309
+ // watchQuery: { fetchPolicy: 'cache-and-network' },
310
+ // },
311
+
312
+ // DevTools are enabled by default in development
313
+ // Only configure when enabling in production
314
+ devtools: {
315
+ enabled: true, // Only needed for production
316
+ },
317
+
318
+ // Custom name for this client instance
319
+ clientAwareness: {
320
+ name: "web-client",
321
+ version: "1.0.0",
322
+ },
323
+ });
324
+ ```
325
+
326
+ ## Important Considerations
327
+
328
+ 1. **Choose Your Hook Strategy:** Decide if your application should be based on Suspense. If it is, use suspenseful hooks like `useSuspenseQuery` (see [Suspense Hooks guide](suspense-hooks.md)), otherwise use non-suspenseful hooks like `useQuery` (see [Queries guide](queries.md)).
329
+
330
+ 2. **Client-Side Only:** This setup is for client-side apps without SSR. The Apollo Client instance is created once and reused throughout the application lifecycle.
331
+
332
+ 3. **Authentication:** Prefer HttpOnly cookies with `credentials: "include"` in `HttpLink` options to avoid exposing tokens to JavaScript. If manual token management is necessary, use `SetContextLink` to dynamically add authentication headers from `localStorage` or other client-side storage.
333
+
334
+ 4. **Environment Variables:** Store your GraphQL endpoint URL in environment variables for different environments (development, staging, production).
335
+
336
+ 5. **Error Handling:** Always handle `loading` and `error` states when using `useQuery` or `useLazyQuery`. For Suspense-based hooks (`useSuspenseQuery`), React handles this through `<Suspense>` boundaries and error boundaries.
@@ -0,0 +1,325 @@
1
+ # Apollo Client Integration with Next.js App Router
2
+
3
+ This guide covers integrating Apollo Client in a Next.js application using the App Router architecture with support for both React Server Components (RSC) and Client Components.
4
+
5
+ ## What is supported?
6
+
7
+ ### React Server Components
8
+
9
+ Apollo Client provides a shared client instance across all server components for a single request, preventing duplicate GraphQL requests and optimizing server-side rendering.
10
+
11
+ ### React Client Components
12
+
13
+ When using the `app` directory, client components are rendered both on the server (SSR) and in the browser. Apollo Client enables you to execute GraphQL queries on the server and use the results to hydrate your browser-side cache, delivering fully-rendered pages to users.
14
+
15
+ ## Installation
16
+
17
+ Install Apollo Client and the Next.js integration package:
18
+
19
+ ```bash
20
+ npm install @apollo/client@latest @apollo/client-integration-nextjs graphql rxjs
21
+ ```
22
+
23
+ > **TypeScript users:** For type-safe GraphQL operations, see the [TypeScript Code Generation guide](typescript-codegen.md).
24
+
25
+ ## Setup for React Server Components (RSC)
26
+
27
+ ### Step 1: Create Apollo Client Configuration
28
+
29
+ Create an `ApolloClient.ts` file in your app directory:
30
+
31
+ ```typescript
32
+ import { HttpLink } from "@apollo/client";
33
+ import {
34
+ registerApolloClient,
35
+ ApolloClient,
36
+ InMemoryCache,
37
+ } from "@apollo/client-integration-nextjs";
38
+
39
+ export const { getClient, query, PreloadQuery } = registerApolloClient(() => {
40
+ return new ApolloClient({
41
+ cache: new InMemoryCache(),
42
+ link: new HttpLink({
43
+ // Use an absolute URL for SSR (relative URLs cannot be used in SSR)
44
+ uri: "https://your-api.com/graphql",
45
+ fetchOptions: {
46
+ // Optional: Next.js-specific fetch options for caching and revalidation
47
+ // See: https://nextjs.org/docs/app/api-reference/functions/fetch
48
+ },
49
+ }),
50
+ });
51
+ });
52
+ ```
53
+
54
+ ### Step 2: Use in Server Components
55
+
56
+ You can now use the `getClient` function or the `query` shortcut in your server components:
57
+
58
+ ```typescript
59
+ import { query } from "./ApolloClient";
60
+
61
+ async function UserProfile({ userId }: { userId: string }) {
62
+ const { data } = await query({
63
+ query: GET_USER,
64
+ variables: { id: userId },
65
+ });
66
+
67
+ return <div>{data.user.name}</div>;
68
+ }
69
+ ```
70
+
71
+ ### Override Next.js Fetch Options
72
+
73
+ You can override Next.js-specific `fetch` options per query using `context.fetchOptions`:
74
+
75
+ ```typescript
76
+ const { data } = await getClient().query({
77
+ query: GET_USER,
78
+ context: {
79
+ fetchOptions: {
80
+ next: { revalidate: 60 }, // Revalidate every 60 seconds
81
+ },
82
+ },
83
+ });
84
+ ```
85
+
86
+ ## Setup for Client Components (SSR and Browser)
87
+
88
+ ### Step 1: Create Apollo Wrapper Component
89
+
90
+ Create `app/ApolloWrapper.tsx`:
91
+
92
+ ```typescript
93
+ "use client";
94
+
95
+ import { HttpLink } from "@apollo/client";
96
+ import {
97
+ ApolloNextAppProvider,
98
+ ApolloClient,
99
+ InMemoryCache,
100
+ } from "@apollo/client-integration-nextjs";
101
+
102
+ function makeClient() {
103
+ const httpLink = new HttpLink({
104
+ // Use an absolute URL for SSR
105
+ uri: "https://your-api.com/graphql",
106
+ fetchOptions: {
107
+ // Optional: Next.js-specific fetch options
108
+ // Note: This doesn't work with `export const dynamic = "force-static"`
109
+ },
110
+ });
111
+
112
+ return new ApolloClient({
113
+ cache: new InMemoryCache(),
114
+ link: httpLink,
115
+ });
116
+ }
117
+
118
+ export function ApolloWrapper({ children }: React.PropsWithChildren) {
119
+ return (
120
+ <ApolloNextAppProvider makeClient={makeClient}>
121
+ {children}
122
+ </ApolloNextAppProvider>
123
+ );
124
+ }
125
+ ```
126
+
127
+ ### Step 2: Wrap Root Layout
128
+
129
+ Wrap your `RootLayout` in the `ApolloWrapper` component in `app/layout.tsx`:
130
+
131
+ ```typescript
132
+ import { ApolloWrapper } from "./ApolloWrapper";
133
+
134
+ export default function RootLayout({
135
+ children,
136
+ }: {
137
+ children: React.ReactNode;
138
+ }) {
139
+ return (
140
+ <html lang="en">
141
+ <body>
142
+ <ApolloWrapper>{children}</ApolloWrapper>
143
+ </body>
144
+ </html>
145
+ );
146
+ }
147
+ ```
148
+
149
+ > **Note:** This works even if your layout is a React Server Component. It ensures all Client Components share the same Apollo Client instance through `ApolloNextAppProvider`.
150
+
151
+ ### Step 3: Use Apollo Client Hooks in Client Components
152
+
153
+ For optimal streaming SSR, use suspense-enabled hooks like `useSuspenseQuery` and `useFragment`:
154
+
155
+ ```typescript
156
+ "use client";
157
+
158
+ import { useSuspenseQuery } from "@apollo/client/react";
159
+
160
+ export function UserProfile({ userId }: { userId: string }) {
161
+ const { data } = useSuspenseQuery(GET_USER, {
162
+ variables: { id: userId },
163
+ });
164
+
165
+ return <div>{data.user.name}</div>;
166
+ }
167
+ ```
168
+
169
+ ## Preloading Data from RSC to Client Components
170
+
171
+ You can preload data in React Server Components to populate the cache of your Client Components.
172
+
173
+ ### Step 1: Use PreloadQuery in Server Components
174
+
175
+ ```tsx
176
+ import { PreloadQuery } from "./ApolloClient";
177
+ import { Suspense } from "react";
178
+
179
+ export default async function Page() {
180
+ return (
181
+ <PreloadQuery query={GET_USER} variables={{ id: "1" }}>
182
+ <Suspense fallback={<>Loading...</>}>
183
+ <ClientChild />
184
+ </Suspense>
185
+ </PreloadQuery>
186
+ );
187
+ }
188
+ ```
189
+
190
+ ### Step 2: Consume with useSuspenseQuery in Client Components
191
+
192
+ ```tsx
193
+ "use client";
194
+
195
+ import { useSuspenseQuery } from "@apollo/client/react";
196
+
197
+ export function ClientChild() {
198
+ const { data } = useSuspenseQuery(GET_USER, {
199
+ variables: { id: "1" },
200
+ });
201
+
202
+ return <div>{data.user.name}</div>;
203
+ }
204
+ ```
205
+
206
+ > **Important:** Data fetched this way should be considered client data and never referenced in Server Components. `PreloadQuery` prevents mixing server data and client data by creating a separate `ApolloClient` instance.
207
+
208
+ ### Using with useReadQuery
209
+
210
+ For advanced use cases, you can use `PreloadQuery` with `useReadQuery` to avoid request waterfalls:
211
+
212
+ ```tsx
213
+ <PreloadQuery query={GET_USER} variables={{ id: "1" }}>
214
+ {(queryRef) => (
215
+ <Suspense fallback={<>Loading...</>}>
216
+ <ClientChild queryRef={queryRef} />
217
+ </Suspense>
218
+ )}
219
+ </PreloadQuery>
220
+ ```
221
+
222
+ In your Client Component:
223
+
224
+ ```tsx
225
+ "use client";
226
+
227
+ import {
228
+ useQueryRefHandlers,
229
+ useReadQuery,
230
+ QueryRef,
231
+ } from "@apollo/client/react";
232
+
233
+ export function ClientChild({ queryRef }: { queryRef: QueryRef<TQueryData> }) {
234
+ const { refetch } = useQueryRefHandlers(queryRef);
235
+ const { data } = useReadQuery(queryRef);
236
+
237
+ return <div>{data.user.name}</div>;
238
+ }
239
+ ```
240
+
241
+ ## Handling Multipart Responses (@defer) in SSR
242
+
243
+ When using the `@defer` directive, `useSuspenseQuery` will only suspend until the initial response is received. To handle deferred data properly, you have three strategies:
244
+
245
+ ### Strategy 1: Use PreloadQuery with useReadQuery
246
+
247
+ `PreloadQuery` allows deferred data to be fully transported and streamed chunk-by-chunk.
248
+
249
+ ### Strategy 2: Remove @defer Fragments
250
+
251
+ Use `RemoveMultipartDirectivesLink` to strip `@defer` directives from queries during SSR:
252
+
253
+ ```typescript
254
+ import { RemoveMultipartDirectivesLink } from "@apollo/client-integration-nextjs";
255
+
256
+ new RemoveMultipartDirectivesLink({
257
+ stripDefer: true, // Default: true
258
+ });
259
+ ```
260
+
261
+ You can exclude specific fragments from stripping by labeling them:
262
+
263
+ ```graphql
264
+ query myQuery {
265
+ fastField
266
+ ... @defer(label: "SsrDontStrip1") {
267
+ slowField1
268
+ }
269
+ }
270
+ ```
271
+
272
+ ### Strategy 3: Wait for Deferred Data
273
+
274
+ Use `AccumulateMultipartResponsesLink` to debounce the initial response:
275
+
276
+ ```typescript
277
+ import { AccumulateMultipartResponsesLink } from "@apollo/client-integration-nextjs";
278
+
279
+ new AccumulateMultipartResponsesLink({
280
+ cutoffDelay: 100, // Wait up to 100ms for incremental data
281
+ });
282
+ ```
283
+
284
+ ### Combined Approach: SSRMultipartLink
285
+
286
+ Combine both strategies with `SSRMultipartLink`:
287
+
288
+ ```typescript
289
+ import { SSRMultipartLink } from "@apollo/client-integration-nextjs";
290
+
291
+ new SSRMultipartLink({
292
+ stripDefer: true,
293
+ cutoffDelay: 100,
294
+ });
295
+ ```
296
+
297
+ ## Testing
298
+
299
+ Reset singleton instances between tests using the `resetApolloClientSingletons` helper:
300
+
301
+ ```typescript
302
+ import { resetApolloClientSingletons } from "@apollo/client-integration-nextjs";
303
+
304
+ afterEach(resetApolloClientSingletons);
305
+ ```
306
+
307
+ ## Debugging
308
+
309
+ Enable verbose logging in your `app/ApolloWrapper.tsx`:
310
+
311
+ ```typescript
312
+ import { setLogVerbosity } from "@apollo/client";
313
+
314
+ setLogVerbosity("debug");
315
+ ```
316
+
317
+ ## Important Considerations
318
+
319
+ 1. **Separate RSC and SSR Queries:** Avoid overlapping queries between RSC and SSR. RSC queries don't update in the browser, while SSR queries can update dynamically as the cache changes.
320
+
321
+ 2. **Use Absolute URLs:** Always use absolute URLs in `HttpLink` for SSR, as relative URLs cannot be used in server-side rendering.
322
+
323
+ 3. **Streaming SSR:** For optimal performance, use `useSuspenseQuery` and `useFragment` to take advantage of React 18's streaming SSR capabilities.
324
+
325
+ 4. **Suspense Boundaries:** Place `Suspense` boundaries at meaningful places in your UI for the best user experience.