@apollo/client 4.2.0-alpha.2 → 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 (78) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/__cjs/core/ApolloClient.cjs +9 -9
  3. package/__cjs/core/ApolloClient.cjs.map +1 -1
  4. package/__cjs/core/ApolloClient.d.cts +131 -21
  5. package/__cjs/link/ws/index.cjs +9 -1
  6. package/__cjs/link/ws/index.cjs.map +1 -1
  7. package/__cjs/link/ws/index.d.cts +1 -1
  8. package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
  9. package/__cjs/react/hooks/useBackgroundQuery.d.cts +1466 -65
  10. package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
  11. package/__cjs/react/hooks/useLazyQuery.d.cts +346 -39
  12. package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
  13. package/__cjs/react/hooks/useLoadableQuery.d.cts +492 -49
  14. package/__cjs/react/hooks/useMutation.cjs +5 -48
  15. package/__cjs/react/hooks/useMutation.cjs.map +1 -1
  16. package/__cjs/react/hooks/useMutation.d.cts +239 -130
  17. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  18. package/__cjs/react/hooks/useQuery.d.cts +570 -40
  19. package/__cjs/react/hooks/useSubscription.cjs +1 -1
  20. package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
  21. package/__cjs/react/hooks/useSubscription.d.cts +2 -2
  22. package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
  23. package/__cjs/react/hooks/useSuspenseQuery.d.cts +734 -45
  24. package/__cjs/version.cjs +1 -1
  25. package/core/ApolloClient.d.ts +131 -21
  26. package/core/ApolloClient.js +9 -9
  27. package/core/ApolloClient.js.map +1 -1
  28. package/link/ws/index.d.ts +1 -1
  29. package/link/ws/index.js +9 -1
  30. package/link/ws/index.js.map +1 -1
  31. package/package.json +3 -7
  32. package/react/hooks/useBackgroundQuery.d.ts +1466 -65
  33. package/react/hooks/useBackgroundQuery.js.map +1 -1
  34. package/react/hooks/useLazyQuery.d.ts +346 -39
  35. package/react/hooks/useLazyQuery.js.map +1 -1
  36. package/react/hooks/useLoadableQuery.d.ts +492 -49
  37. package/react/hooks/useLoadableQuery.js.map +1 -1
  38. package/react/hooks/useMutation.d.ts +239 -130
  39. package/react/hooks/useMutation.js +5 -48
  40. package/react/hooks/useMutation.js.map +1 -1
  41. package/react/hooks/useQuery.d.ts +570 -40
  42. package/react/hooks/useQuery.js.map +1 -1
  43. package/react/hooks/useSubscription.d.ts +2 -2
  44. package/react/hooks/useSubscription.js +1 -1
  45. package/react/hooks/useSubscription.js.map +1 -1
  46. package/react/hooks/useSuspenseQuery.d.ts +734 -45
  47. package/react/hooks/useSuspenseQuery.js.map +1 -1
  48. package/react/hooks-compiled/useBackgroundQuery.d.ts +1466 -65
  49. package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
  50. package/react/hooks-compiled/useLazyQuery.d.ts +346 -39
  51. package/react/hooks-compiled/useLazyQuery.js.map +1 -1
  52. package/react/hooks-compiled/useLoadableQuery.d.ts +492 -49
  53. package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
  54. package/react/hooks-compiled/useMutation.d.ts +239 -130
  55. package/react/hooks-compiled/useMutation.js +4 -47
  56. package/react/hooks-compiled/useMutation.js.map +1 -1
  57. package/react/hooks-compiled/useQuery.d.ts +570 -40
  58. package/react/hooks-compiled/useQuery.js.map +1 -1
  59. package/react/hooks-compiled/useSubscription.d.ts +2 -2
  60. package/react/hooks-compiled/useSubscription.js +1 -1
  61. package/react/hooks-compiled/useSubscription.js.map +1 -1
  62. package/react/hooks-compiled/useSuspenseQuery.d.ts +734 -45
  63. package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
  64. package/skills/apollo-client/SKILL.md +168 -0
  65. package/skills/apollo-client/references/caching.md +560 -0
  66. package/skills/apollo-client/references/error-handling.md +350 -0
  67. package/skills/apollo-client/references/fragments.md +804 -0
  68. package/skills/apollo-client/references/integration-client.md +336 -0
  69. package/skills/apollo-client/references/integration-nextjs.md +325 -0
  70. package/skills/apollo-client/references/integration-react-router.md +256 -0
  71. package/skills/apollo-client/references/integration-tanstack-start.md +378 -0
  72. package/skills/apollo-client/references/mutations.md +549 -0
  73. package/skills/apollo-client/references/queries.md +416 -0
  74. package/skills/apollo-client/references/state-management.md +428 -0
  75. package/skills/apollo-client/references/suspense-hooks.md +773 -0
  76. package/skills/apollo-client/references/troubleshooting.md +487 -0
  77. package/skills/apollo-client/references/typescript-codegen.md +133 -0
  78. package/version.js +1 -1
@@ -0,0 +1,416 @@
1
+ # Queries Reference
2
+
3
+ > **Note**: In most applications, there should only be one use of a query hook per page. Use fragment-reading hooks (`useFragment`, `useSuspenseFragment`) with component-colocated fragments and data masking for the rest of the page components.
4
+
5
+ ## Table of Contents
6
+
7
+ - [useQuery Hook](#usequery-hook)
8
+ - [Query Variables](#query-variables)
9
+ - [Loading and Error States](#loading-and-error-states)
10
+ - [useLazyQuery](#uselazyquery)
11
+ - [Polling and Refetching](#polling-and-refetching)
12
+ - [Fetch Policies](#fetch-policies)
13
+ - [Conditional Queries](#conditional-queries)
14
+
15
+ ## useQuery Hook
16
+
17
+ The `useQuery` hook is the primary way to fetch data in Apollo Client in non-suspenseful applications. It returns loading and error states that must be handled.
18
+
19
+ > **Note**: In suspenseful applications, use `useSuspenseQuery` or `useBackgroundQuery` instead. See the [Suspense Hooks reference](suspense-hooks.md) for more details.
20
+
21
+ ### Basic Usage
22
+
23
+ ```tsx
24
+ import { gql } from "@apollo/client";
25
+ import { useQuery } from "@apollo/client/react";
26
+
27
+ const GET_DOGS = gql`
28
+ query GetDogs {
29
+ dogs {
30
+ id
31
+ breed
32
+ displayImage
33
+ }
34
+ }
35
+ `;
36
+
37
+ function Dogs() {
38
+ const { loading, error, data } = useQuery(GET_DOGS);
39
+
40
+ if (loading) return <p>Loading...</p>;
41
+ if (error) return <p>Error: {error.message}</p>;
42
+
43
+ return <ul>{data?.dogs.map((dog) => <li key={dog.id}>{dog.breed}</li>)}</ul>;
44
+ }
45
+ ```
46
+
47
+ ### Return Object
48
+
49
+ ```typescript
50
+ const {
51
+ data, // Query result data
52
+ loading, // True during initial load
53
+ error, // ApolloError if request failed
54
+ networkStatus, // Detailed network state (1-8)
55
+ dataState, // For TypeScript type narrowing (AC 4.x)
56
+ refetch, // Function to re-execute query
57
+ fetchMore, // Function for pagination
58
+ startPolling, // Start polling at interval
59
+ stopPolling, // Stop polling
60
+ subscribeToMore, // Add subscription to query
61
+ updateQuery, // Manually update query result
62
+ client, // Apollo Client instance
63
+ called, // True if query has been executed
64
+ previousData, // Previous data (useful during loading)
65
+ } = useQuery(QUERY);
66
+ ```
67
+
68
+ ## Query Variables
69
+
70
+ ### Basic Variables
71
+
72
+ ```tsx
73
+ const GET_DOG = gql`
74
+ query GetDog($breed: String!) {
75
+ dog(breed: $breed) {
76
+ id
77
+ displayImage
78
+ }
79
+ }
80
+ `;
81
+
82
+ function DogPhoto({ breed }: { breed: string }) {
83
+ const { loading, error, data } = useQuery(GET_DOG, {
84
+ variables: { breed },
85
+ });
86
+
87
+ if (loading) return null;
88
+ if (error) return <p>Error: {error.message}</p>;
89
+
90
+ return <img src={data.dog.displayImage} alt={breed} />;
91
+ }
92
+ ```
93
+
94
+ ### TypeScript Types
95
+
96
+ Use `TypedDocumentNode` instead of generic type parameters for better type safety:
97
+
98
+ ```typescript
99
+ import { gql, TypedDocumentNode } from "@apollo/client";
100
+ import { useQuery } from "@apollo/client/react";
101
+
102
+ interface GetDogData {
103
+ dog: {
104
+ id: string;
105
+ displayImage: string;
106
+ };
107
+ }
108
+
109
+ interface GetDogVariables {
110
+ breed: string;
111
+ }
112
+
113
+ const GET_DOG: TypedDocumentNode<GetDogData, GetDogVariables> = gql`
114
+ query GetDog($breed: String!) {
115
+ dog(breed: $breed) {
116
+ id
117
+ displayImage
118
+ }
119
+ }
120
+ `;
121
+
122
+ const { data } = useQuery(GET_DOG, {
123
+ variables: { breed: "bulldog" },
124
+ });
125
+
126
+ // data?.dog is fully typed
127
+ ```
128
+
129
+ ### Dynamic Variables
130
+
131
+ ```tsx
132
+ function DogSelector() {
133
+ const [breed, setBreed] = useState("bulldog");
134
+
135
+ // Query automatically re-runs when breed changes
136
+ const { data } = useQuery(GET_DOG, {
137
+ variables: { breed },
138
+ });
139
+
140
+ return (
141
+ <select value={breed} onChange={(e) => setBreed(e.target.value)}>
142
+ <option value="bulldog">Bulldog</option>
143
+ <option value="poodle">Poodle</option>
144
+ </select>
145
+ );
146
+ }
147
+ ```
148
+
149
+ ## Loading and Error States
150
+
151
+ ### Using Previous Data
152
+
153
+ ```tsx
154
+ function UserProfile({ userId }: { userId: string }) {
155
+ const { loading, data, previousData } = useQuery(GET_USER, {
156
+ variables: { id: userId },
157
+ });
158
+
159
+ // Show previous data while loading new data
160
+ const displayData = data ?? previousData;
161
+
162
+ return (
163
+ <div>
164
+ {loading && <LoadingSpinner />}
165
+ {displayData && <UserCard user={displayData.user} />}
166
+ </div>
167
+ );
168
+ }
169
+ ```
170
+
171
+ ### Network Status
172
+
173
+ ```tsx
174
+ import { NetworkStatus } from "@apollo/client";
175
+
176
+ function Dogs() {
177
+ const { loading, error, data, networkStatus, refetch } = useQuery(GET_DOGS, {
178
+ notifyOnNetworkStatusChange: true,
179
+ });
180
+
181
+ if (networkStatus === NetworkStatus.refetch) {
182
+ return <p>Refetching...</p>;
183
+ }
184
+
185
+ if (loading) return <p>Loading...</p>;
186
+ if (error) return <p>Error: {error.message}</p>;
187
+
188
+ return (
189
+ <>
190
+ <button onClick={() => refetch()}>Refresh</button>
191
+ <ul>
192
+ {data.dogs.map((dog) => (
193
+ <li key={dog.id}>{dog.breed}</li>
194
+ ))}
195
+ </ul>
196
+ </>
197
+ );
198
+ }
199
+ ```
200
+
201
+ ## useLazyQuery
202
+
203
+ Use `useLazyQuery` when you want to execute a query in response to a user-triggered event (like a button click) rather than on component mount.
204
+
205
+ **Important**: `useLazyQuery` doesn't guarantee a network request - it only sets variables. If data is already in the cache, this isn't a "refetch". Only use `useLazyQuery` if you consume the second tuple value (loading, data, error states) to synchronize cache data with the component. If you only need the promise, use `client.query` directly instead.
206
+
207
+ ### Basic Usage
208
+
209
+ ```tsx
210
+ import { gql } from "@apollo/client";
211
+ import { useLazyQuery } from "@apollo/client/react";
212
+
213
+ const GET_DOG_PHOTO = gql`
214
+ query GetDogPhoto($breed: String!) {
215
+ dog(breed: $breed) {
216
+ id
217
+ displayImage
218
+ }
219
+ }
220
+ `;
221
+
222
+ function DelayedQuery() {
223
+ const [getDog, { loading, error, data, called }] =
224
+ useLazyQuery(GET_DOG_PHOTO);
225
+
226
+ if (called && loading) return <p>Loading...</p>;
227
+ if (error) return <p>Error: {error.message}</p>;
228
+
229
+ return (
230
+ <div>
231
+ {data?.dog && <img src={data.dog.displayImage} />}
232
+ <button onClick={() => getDog({ variables: { breed: "bulldog" } })}>
233
+ Get Bulldog Photo
234
+ </button>
235
+ </div>
236
+ );
237
+ }
238
+ ```
239
+
240
+ ### When to Use client.query Instead
241
+
242
+ If you only need the promise result and don't consume the loading/error/data states from the hook, use `client.query` instead:
243
+
244
+ ```tsx
245
+ import { useApolloClient } from "@apollo/client/react";
246
+
247
+ function SearchDogs() {
248
+ const client = useApolloClient();
249
+ const [search, setSearch] = useState("");
250
+
251
+ const handleSearch = async () => {
252
+ try {
253
+ const { data } = await client.query({
254
+ query: SEARCH_DOGS,
255
+ variables: { query: search },
256
+ });
257
+ console.log("Found dogs:", data.searchDogs);
258
+ } catch (error) {
259
+ console.error("Search failed:", error);
260
+ }
261
+ };
262
+
263
+ return (
264
+ <div>
265
+ <input value={search} onChange={(e) => setSearch(e.target.value)} />
266
+ <button onClick={handleSearch}>Search</button>
267
+ </div>
268
+ );
269
+ }
270
+ ```
271
+
272
+ ## Polling and Refetching
273
+
274
+ ### Polling
275
+
276
+ ```tsx
277
+ function LiveFeed() {
278
+ const { data, startPolling, stopPolling } = useQuery(GET_FEED, {
279
+ pollInterval: 5000, // Poll every 5 seconds
280
+ });
281
+
282
+ // Or control polling dynamically
283
+ useEffect(() => {
284
+ startPolling(5000);
285
+ return () => stopPolling();
286
+ }, [startPolling, stopPolling]);
287
+
288
+ return <Feed items={data?.feed} />;
289
+ }
290
+ ```
291
+
292
+ ### Manual Refetching
293
+
294
+ ```tsx
295
+ function DogList() {
296
+ const { data, refetch } = useQuery(GET_DOGS);
297
+
298
+ return (
299
+ <div>
300
+ <button onClick={() => refetch()}>Refresh</button>
301
+ <button onClick={() => refetch({ breed: "poodle" })}>
302
+ Refetch Poodles
303
+ </button>
304
+ <ul>{data?.dogs.map((dog) => <li key={dog.id}>{dog.breed}</li>)}</ul>
305
+ </div>
306
+ );
307
+ }
308
+ ```
309
+
310
+ ## Fetch Policies
311
+
312
+ Control how the query interacts with the cache.
313
+
314
+ | Policy | Description |
315
+ | ------------------- | ---------------------------------------------------------- |
316
+ | `cache-first` | Return cached data if available, otherwise fetch (default) |
317
+ | `cache-only` | Only return cached data, never fetch |
318
+ | `cache-and-network` | Return cached data immediately, then fetch and update |
319
+ | `network-only` | Always fetch, update cache, ignore cached data |
320
+ | `no-cache` | Always fetch, never read or write cache |
321
+ | `standby` | Same as cache-first but doesn't auto-update |
322
+
323
+ ### Usage Examples
324
+
325
+ ```tsx
326
+ // Real-time data - always fetch
327
+ const { data } = useQuery(GET_NOTIFICATIONS, {
328
+ fetchPolicy: "network-only",
329
+ });
330
+
331
+ // Static data - prefer cache
332
+ const { data } = useQuery(GET_CATEGORIES, {
333
+ fetchPolicy: "cache-first",
334
+ });
335
+
336
+ // Show cached data while fetching fresh data
337
+ const { data, loading } = useQuery(GET_POSTS, {
338
+ fetchPolicy: "cache-and-network",
339
+ });
340
+
341
+ // Fetch once, then use cache
342
+ const { data } = useQuery(GET_USER_PROFILE, {
343
+ fetchPolicy: "network-only",
344
+ nextFetchPolicy: "cache-first",
345
+ });
346
+ ```
347
+
348
+ ### nextFetchPolicy
349
+
350
+ ```tsx
351
+ // First request: network-only
352
+ // Subsequent requests: cache-first
353
+ const { data } = useQuery(GET_POSTS, {
354
+ fetchPolicy: "network-only",
355
+ nextFetchPolicy: "cache-first",
356
+ });
357
+
358
+ // Or use a function for more control
359
+ const { data } = useQuery(GET_POSTS, {
360
+ fetchPolicy: "network-only",
361
+ nextFetchPolicy: (currentFetchPolicy, { reason, observable }) => {
362
+ if (reason === "after-fetch") {
363
+ return "cache-first";
364
+ }
365
+ return currentFetchPolicy;
366
+ },
367
+ });
368
+ ```
369
+
370
+ ## Conditional Queries
371
+
372
+ ### Using skipToken (Recommended)
373
+
374
+ Use `skipToken` to conditionally skip queries without TypeScript issues:
375
+
376
+ ```tsx
377
+ import { skipToken } from "@apollo/client";
378
+
379
+ function UserProfile({ userId }: { userId: string | null }) {
380
+ const { data } = useQuery(
381
+ GET_USER,
382
+ !userId ? skipToken : (
383
+ {
384
+ variables: { id: userId },
385
+ }
386
+ )
387
+ );
388
+
389
+ return userId ? <Profile user={data?.user} /> : <p>Select a user</p>;
390
+ }
391
+ ```
392
+
393
+ ### Skip Option (Alternative)
394
+
395
+ ```tsx
396
+ function UserProfile({ userId }: { userId: string | null }) {
397
+ const { data } = useQuery(GET_USER, {
398
+ variables: { id: userId! },
399
+ skip: !userId, // Don't execute if no userId
400
+ });
401
+
402
+ return userId ? <Profile user={data?.user} /> : <p>Select a user</p>;
403
+ }
404
+ ```
405
+
406
+ > **Note**: Using `skipToken` is preferred over `skip` as it avoids TypeScript issues with required variables and the non-null assertion operator.
407
+
408
+ ### SSR Skip
409
+
410
+ ```tsx
411
+ // Skip during server-side rendering
412
+ const { data } = useQuery(GET_USER_LOCATION, {
413
+ skip: typeof window === "undefined",
414
+ ssr: false,
415
+ });
416
+ ```