@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.
- package/CHANGELOG.md +209 -0
- package/__cjs/core/ApolloClient.cjs +25 -12
- package/__cjs/core/ApolloClient.cjs.map +1 -1
- package/__cjs/core/ApolloClient.d.cts +305 -146
- package/__cjs/core/QueryManager.cjs.map +1 -1
- package/__cjs/core/defaultOptions.cjs +3 -0
- package/__cjs/core/defaultOptions.cjs.map +1 -0
- package/__cjs/core/defaultOptions.d.cts +90 -0
- package/__cjs/core/index.cjs.map +1 -1
- package/__cjs/core/index.d.cts +2 -1
- package/__cjs/link/ws/index.cjs +9 -1
- package/__cjs/link/ws/index.cjs.map +1 -1
- package/__cjs/link/ws/index.d.cts +1 -1
- package/__cjs/react/hooks/useBackgroundQuery.cjs +3 -3
- package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useBackgroundQuery.d.cts +1598 -765
- package/__cjs/react/hooks/useLazyQuery.cjs +3 -5
- package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useLazyQuery.d.cts +369 -115
- package/__cjs/react/hooks/useLoadableQuery.cjs +8 -4
- package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useLoadableQuery.d.cts +507 -192
- package/__cjs/react/hooks/useMutation.cjs +5 -48
- package/__cjs/react/hooks/useMutation.cjs.map +1 -1
- package/__cjs/react/hooks/useMutation.d.cts +239 -130
- package/__cjs/react/hooks/useQuery.cjs +5 -5
- package/__cjs/react/hooks/useQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useQuery.d.cts +636 -276
- package/__cjs/react/hooks/useSubscription.cjs +1 -1
- package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
- package/__cjs/react/hooks/useSubscription.d.cts +2 -2
- package/__cjs/react/hooks/useSuspenseQuery.cjs +3 -3
- package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
- package/__cjs/react/hooks/useSuspenseQuery.d.cts +799 -399
- package/__cjs/react/internal/cache/getSuspenseCache.cjs.map +1 -1
- package/__cjs/react/internal/cache/getSuspenseCache.d.cts +7 -0
- package/__cjs/utilities/internal/LazyType.cjs +3 -0
- package/__cjs/utilities/internal/LazyType.cjs.map +1 -0
- package/__cjs/utilities/internal/LazyType.d.cts +10 -0
- package/__cjs/utilities/internal/index.cjs.map +1 -1
- package/__cjs/utilities/internal/index.d.cts +3 -0
- package/__cjs/utilities/internal/types/OptionWithFallback.cjs +3 -0
- package/__cjs/utilities/internal/types/OptionWithFallback.cjs.map +1 -0
- package/__cjs/utilities/internal/types/OptionWithFallback.d.cts +5 -0
- package/__cjs/utilities/internal/types/SignatureStyle.cjs +3 -0
- package/__cjs/utilities/internal/types/SignatureStyle.cjs.map +1 -0
- package/__cjs/utilities/internal/types/SignatureStyle.d.cts +24 -0
- package/__cjs/version.cjs +1 -1
- package/core/ApolloClient.d.ts +305 -146
- package/core/ApolloClient.js +25 -12
- package/core/ApolloClient.js.map +1 -1
- package/core/QueryManager.js.map +1 -1
- package/core/defaultOptions.d.ts +90 -0
- package/core/defaultOptions.js +2 -0
- package/core/defaultOptions.js.map +1 -0
- package/core/index.d.ts +2 -1
- package/core/index.js.map +1 -1
- package/link/ws/index.d.ts +1 -1
- package/link/ws/index.js +9 -1
- package/link/ws/index.js.map +1 -1
- package/package.json +3 -7
- package/react/hooks/useBackgroundQuery.d.ts +1598 -765
- package/react/hooks/useBackgroundQuery.js +2 -2
- package/react/hooks/useBackgroundQuery.js.map +1 -1
- package/react/hooks/useLazyQuery.d.ts +369 -115
- package/react/hooks/useLazyQuery.js +2 -4
- package/react/hooks/useLazyQuery.js.map +1 -1
- package/react/hooks/useLoadableQuery.d.ts +507 -192
- package/react/hooks/useLoadableQuery.js +7 -3
- package/react/hooks/useLoadableQuery.js.map +1 -1
- package/react/hooks/useMutation.d.ts +239 -130
- package/react/hooks/useMutation.js +5 -48
- package/react/hooks/useMutation.js.map +1 -1
- package/react/hooks/useQuery.d.ts +636 -276
- package/react/hooks/useQuery.js +2 -2
- package/react/hooks/useQuery.js.map +1 -1
- package/react/hooks/useSubscription.d.ts +2 -2
- package/react/hooks/useSubscription.js +1 -1
- package/react/hooks/useSubscription.js.map +1 -1
- package/react/hooks/useSuspenseQuery.d.ts +799 -399
- package/react/hooks/useSuspenseQuery.js +2 -2
- package/react/hooks/useSuspenseQuery.js.map +1 -1
- package/react/hooks-compiled/useBackgroundQuery.d.ts +1598 -765
- package/react/hooks-compiled/useBackgroundQuery.js +2 -2
- package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
- package/react/hooks-compiled/useLazyQuery.d.ts +369 -115
- package/react/hooks-compiled/useLazyQuery.js +2 -4
- package/react/hooks-compiled/useLazyQuery.js.map +1 -1
- package/react/hooks-compiled/useLoadableQuery.d.ts +507 -192
- package/react/hooks-compiled/useLoadableQuery.js +2 -2
- package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
- package/react/hooks-compiled/useMutation.d.ts +239 -130
- package/react/hooks-compiled/useMutation.js +4 -47
- package/react/hooks-compiled/useMutation.js.map +1 -1
- package/react/hooks-compiled/useQuery.d.ts +636 -276
- package/react/hooks-compiled/useQuery.js +2 -2
- package/react/hooks-compiled/useQuery.js.map +1 -1
- package/react/hooks-compiled/useSubscription.d.ts +2 -2
- package/react/hooks-compiled/useSubscription.js +1 -1
- package/react/hooks-compiled/useSubscription.js.map +1 -1
- package/react/hooks-compiled/useSuspenseQuery.d.ts +799 -399
- package/react/hooks-compiled/useSuspenseQuery.js +2 -2
- package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
- package/react/internal/cache/getSuspenseCache.d.ts +7 -0
- package/react/internal/cache/getSuspenseCache.js.map +1 -1
- package/skills/apollo-client/SKILL.md +168 -0
- package/skills/apollo-client/references/caching.md +560 -0
- package/skills/apollo-client/references/error-handling.md +350 -0
- package/skills/apollo-client/references/fragments.md +804 -0
- package/skills/apollo-client/references/integration-client.md +336 -0
- package/skills/apollo-client/references/integration-nextjs.md +325 -0
- package/skills/apollo-client/references/integration-react-router.md +256 -0
- package/skills/apollo-client/references/integration-tanstack-start.md +378 -0
- package/skills/apollo-client/references/mutations.md +549 -0
- package/skills/apollo-client/references/queries.md +416 -0
- package/skills/apollo-client/references/state-management.md +428 -0
- package/skills/apollo-client/references/suspense-hooks.md +773 -0
- package/skills/apollo-client/references/troubleshooting.md +487 -0
- package/skills/apollo-client/references/typescript-codegen.md +133 -0
- package/utilities/internal/LazyType.d.ts +10 -0
- package/utilities/internal/LazyType.js +2 -0
- package/utilities/internal/LazyType.js.map +1 -0
- package/utilities/internal/index.d.ts +3 -0
- package/utilities/internal/index.js.map +1 -1
- package/utilities/internal/types/OptionWithFallback.d.ts +5 -0
- package/utilities/internal/types/OptionWithFallback.js +2 -0
- package/utilities/internal/types/OptionWithFallback.js.map +1 -0
- package/utilities/internal/types/SignatureStyle.d.ts +24 -0
- package/utilities/internal/types/SignatureStyle.js +2 -0
- package/utilities/internal/types/SignatureStyle.js.map +1 -0
- 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
|
+
```
|