0
# Query Operations
1
2
Core data fetching functionality with intelligent caching, background updates, and automatic error handling. The `useQuery` hook is the primary interface for fetching and caching data in React Query.
3
4
## Capabilities
5
6
### useQuery Hook
7
8
The main hook for fetching data with automatic caching and background updates.
9
10
```typescript { .api }
11
/**
12
* Fetch and cache data with automatic background updates
13
* @param options - Query configuration options
14
* @returns Query result with data, loading states, and utilities
15
*/
16
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
17
options: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
18
): UseQueryResult<TData, TError>;
19
20
/**
21
* Fetch and cache data using separate queryKey and queryFn parameters
22
* @param queryKey - Unique identifier for the query
23
* @param queryFn - Function that returns data or promise
24
* @param options - Additional query configuration
25
* @returns Query result with data, loading states, and utilities
26
*/
27
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
28
queryKey: TQueryKey,
29
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
30
options?: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>
31
): UseQueryResult<TData, TError>;
32
33
/**
34
* Fetch and cache data with optional undefined initial data
35
* @param options - Query configuration with optional initialData
36
* @returns Query result where data may be undefined
37
*/
38
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
39
options: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData'> & {
40
initialData?: () => undefined
41
}
42
): UseQueryResult<TData, TError>;
43
44
/**
45
* Fetch and cache data with guaranteed initial data
46
* @param options - Query configuration with initialData
47
* @returns Defined query result where data is never undefined
48
*/
49
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
50
options: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'initialData'> & {
51
initialData: TQueryFnData | (() => TQueryFnData)
52
}
53
): DefinedUseQueryResult<TData, TError>;
54
55
/**
56
* Fetch and cache data with separate parameters and optional undefined initial data
57
* @param queryKey - Unique identifier for the query
58
* @param options - Query configuration with optional initialData
59
* @returns Query result where data may be undefined
60
*/
61
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
62
queryKey: TQueryKey,
63
options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'initialData'> & {
64
initialData?: () => undefined
65
}
66
): UseQueryResult<TData, TError>;
67
68
/**
69
* Fetch and cache data with separate parameters and guaranteed initial data
70
* @param queryKey - Unique identifier for the query
71
* @param options - Query configuration with initialData
72
* @returns Defined query result where data is never undefined
73
*/
74
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
75
queryKey: TQueryKey,
76
options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'initialData'> & {
77
initialData: TQueryFnData | (() => TQueryFnData)
78
}
79
): DefinedUseQueryResult<TData, TError>;
80
81
/**
82
* Fetch and cache data with queryKey, queryFn and optional undefined initial data
83
* @param queryKey - Unique identifier for the query
84
* @param queryFn - Function that returns data or promise
85
* @param options - Additional query configuration with optional initialData
86
* @returns Query result where data may be undefined
87
*/
88
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
89
queryKey: TQueryKey,
90
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
91
options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'queryFn' | 'initialData'> & {
92
initialData?: () => undefined
93
}
94
): UseQueryResult<TData, TError>;
95
96
/**
97
* Fetch and cache data with queryKey, queryFn and guaranteed initial data
98
* @param queryKey - Unique identifier for the query
99
* @param queryFn - Function that returns data or promise
100
* @param options - Additional query configuration with initialData
101
* @returns Defined query result where data is never undefined
102
*/
103
function useQuery<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(
104
queryKey: TQueryKey,
105
queryFn: QueryFunction<TQueryFnData, TQueryKey>,
106
options?: Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'queryKey' | 'queryFn' | 'initialData'> & {
107
initialData: TQueryFnData | (() => TQueryFnData)
108
}
109
): DefinedUseQueryResult<TData, TError>;
110
```
111
112
**Usage Examples:**
113
114
```typescript
115
import { useQuery } from "react-query";
116
117
// Basic query
118
const { data, isLoading, error } = useQuery({
119
queryKey: ['posts'],
120
queryFn: () => fetch('/api/posts').then(res => res.json())
121
});
122
123
// Query with parameters
124
const { data: user } = useQuery({
125
queryKey: ['user', userId],
126
queryFn: ({ queryKey }) => fetch(`/api/users/${queryKey[1]}`).then(res => res.json()),
127
enabled: !!userId // Only run when userId exists
128
});
129
130
// Query with data transformation
131
const { data: userNames } = useQuery({
132
queryKey: ['users'],
133
queryFn: () => fetch('/api/users').then(res => res.json()),
134
select: (users) => users.map(user => user.name)
135
});
136
137
// Legacy API style (separate parameters)
138
const { data } = useQuery(
139
['posts', { page: 1 }],
140
({ queryKey }) => fetchPosts(queryKey[1]),
141
{
142
staleTime: 5000,
143
retry: 3
144
}
145
);
146
```
147
148
### Query Result Interface
149
150
The return value from `useQuery` containing data, loading states, and utilities.
151
152
```typescript { .api }
153
interface UseQueryResult<TData = unknown, TError = unknown> {
154
/** The actual data returned by the query function */
155
data: TData | undefined;
156
/** The error object if the query failed */
157
error: TError | null;
158
/** True if the query is in an error state */
159
isError: boolean;
160
/** True if this is the first time the query is loading */
161
isLoading: boolean;
162
/** True if the query is pending (loading or paused) */
163
isPending: boolean;
164
/** True if the query succeeded and has data */
165
isSuccess: boolean;
166
/** True if the query is currently fetching */
167
isFetching: boolean;
168
/** True if the query is refetching in the background */
169
isRefetching: boolean;
170
/** Current status of the query */
171
status: 'pending' | 'error' | 'success';
172
/** Current fetch status */
173
fetchStatus: 'fetching' | 'paused' | 'idle';
174
/** Function to manually refetch the query */
175
refetch: () => Promise<QueryObserverResult<TData, TError>>;
176
/** Function to remove the query from cache */
177
remove: () => void;
178
/** Timestamp when data was last updated */
179
dataUpdatedAt: number;
180
/** Timestamp when error occurred */
181
errorUpdatedAt: number;
182
/** Number of times query has failed */
183
failureCount: number;
184
/** Reason query is paused */
185
failureReason: TError | null;
186
/** True if query data is stale */
187
isStale: boolean;
188
/** True if initial data was provided */
189
isInitialLoading: boolean;
190
/** True if refetch is disabled */
191
isRefetchError: boolean;
192
/** True if loading first time due to error */
193
isLoadingError: boolean;
194
/** True if currently paused */
195
isPaused: boolean;
196
/** True if data exists in cache */
197
isPlaceholderData: boolean;
198
/** Previous successful data */
199
isPreviousData: boolean;
200
}
201
202
interface DefinedUseQueryResult<TData = unknown, TError = unknown>
203
extends Omit<UseQueryResult<TData, TError>, 'data'> {
204
/** Data is guaranteed to be defined */
205
data: TData;
206
}
207
```
208
209
### Query Options Interface
210
211
Configuration options for `useQuery` hook.
212
213
```typescript { .api }
214
interface UseQueryOptions<TQueryFnData = unknown, TError = unknown, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey> {
215
/** Unique identifier for the query */
216
queryKey?: TQueryKey;
217
/** Function that returns data or promise */
218
queryFn?: QueryFunction<TQueryFnData, TQueryKey>;
219
/** Whether the query should run automatically */
220
enabled?: boolean;
221
/** Retry configuration */
222
retry?: boolean | number | ((failureCount: number, error: TError) => boolean);
223
/** Delay between retries */
224
retryDelay?: number | ((retryAttempt: number, error: TError) => number);
225
/** Time before data is considered stale */
226
staleTime?: number;
227
/** Time before inactive queries are garbage collected */
228
cacheTime?: number;
229
/** Interval for automatic refetching */
230
refetchInterval?: number | false | ((data: TData | undefined, query: Query) => number | false);
231
/** Whether to refetch when window is not focused */
232
refetchIntervalInBackground?: boolean;
233
/** When to refetch on component mount */
234
refetchOnMount?: boolean | "always";
235
/** When to refetch on window focus */
236
refetchOnWindowFocus?: boolean | "always";
237
/** When to refetch on network reconnection */
238
refetchOnReconnect?: boolean | "always";
239
/** Transform or select data subset */
240
select?: (data: TQueryFnData) => TData;
241
/** Initial data to use before first fetch */
242
initialData?: TData | (() => TData);
243
/** Placeholder data while loading */
244
placeholderData?: TData | (() => TData);
245
/** Callback on successful query */
246
onSuccess?: (data: TData) => void;
247
/** Callback on query error */
248
onError?: (error: TError) => void;
249
/** Callback after query settles (success or error) */
250
onSettled?: (data: TData | undefined, error: TError | null) => void;
251
/** React context for QueryClient */
252
context?: React.Context<QueryClient | undefined>;
253
/** Whether to throw errors to error boundaries */
254
useErrorBoundary?: boolean | ((error: TError, query: Query) => boolean);
255
/** Whether to suspend component rendering */
256
suspense?: boolean;
257
/** Whether to keep previous data during refetch */
258
keepPreviousData?: boolean;
259
/** Network mode configuration */
260
networkMode?: 'online' | 'always' | 'offlineFirst';
261
/** Notification mode configuration */
262
notifyOnChangeProps?: Array<keyof UseQueryResult> | 'all';
263
/** Additional metadata */
264
meta?: QueryMeta;
265
}
266
```
267
268
### Query Function Interface
269
270
The function that actually fetches data for the query.
271
272
```typescript { .api }
273
type QueryFunction<T = unknown, TQueryKey extends QueryKey = QueryKey> = (
274
context: QueryFunctionContext<TQueryKey>
275
) => T | Promise<T>;
276
277
interface QueryFunctionContext<TQueryKey extends QueryKey = QueryKey, TPageParam = any> {
278
/** The query key */
279
queryKey: TQueryKey;
280
/** AbortSignal for request cancellation */
281
signal?: AbortSignal;
282
/** Page parameter for infinite queries */
283
pageParam?: TPageParam;
284
/** Additional metadata */
285
meta: QueryMeta | undefined;
286
}
287
288
type QueryKey = readonly unknown[];
289
290
type QueryMeta = Record<string, unknown>;
291
```
292
293
## Advanced Usage Patterns
294
295
### Dependent Queries
296
297
Queries that depend on data from other queries:
298
299
```typescript
300
function Profile({ userId }: { userId: string }) {
301
// First, get the user
302
const { data: user } = useQuery({
303
queryKey: ['user', userId],
304
queryFn: () => fetchUser(userId)
305
});
306
307
// Then get user's posts (depends on user data)
308
const { data: posts } = useQuery({
309
queryKey: ['posts', user?.id],
310
queryFn: () => fetchUserPosts(user.id),
311
enabled: !!user?.id
312
});
313
314
return <div>{/* render user and posts */}</div>;
315
}
316
```
317
318
### Dynamic Query Keys
319
320
Query keys that change based on component state:
321
322
```typescript
323
function SearchResults() {
324
const [searchTerm, setSearchTerm] = useState('');
325
const [filters, setFilters] = useState({});
326
327
const { data: results } = useQuery({
328
queryKey: ['search', searchTerm, filters],
329
queryFn: ({ queryKey }) => searchAPI(queryKey[1], queryKey[2]),
330
enabled: searchTerm.length > 2
331
});
332
333
return (
334
<div>
335
<input
336
value={searchTerm}
337
onChange={(e) => setSearchTerm(e.target.value)}
338
/>
339
{/* render results */}
340
</div>
341
);
342
}
343
```
344
345
### Error Handling
346
347
```typescript
348
const { data, error, isError, refetch } = useQuery({
349
queryKey: ['posts'],
350
queryFn: fetchPosts,
351
retry: (failureCount, error) => {
352
// Retry up to 3 times for server errors
353
if (error.status >= 500 && failureCount < 3) {
354
return true;
355
}
356
return false;
357
},
358
onError: (error) => {
359
console.error('Query failed:', error);
360
// Could show toast notification, log to analytics, etc.
361
}
362
});
363
364
if (isError) {
365
return (
366
<div>
367
<p>Something went wrong: {error.message}</p>
368
<button onClick={() => refetch()}>Try Again</button>
369
</div>
370
);
371
}
372
```