0
# Core Data Fetching
1
2
The core `useSWR` hook provides comprehensive data fetching capabilities with caching, automatic revalidation, error handling, and loading states.
3
4
## Capabilities
5
6
### useSWR Hook
7
8
The primary hook for data fetching with automatic caching and revalidation.
9
10
```typescript { .api }
11
/**
12
* Primary hook for data fetching with automatic caching and revalidation
13
* @param key - Unique identifier for the request (string, array, object, function, or falsy)
14
* @param fetcher - Function that fetches the data, or null to disable fetching
15
* @param config - Configuration options for this hook instance
16
* @returns SWRResponse object with data, error, loading states, and mutate function
17
*/
18
function useSWR<Data = any, Error = any>(
19
key: Key,
20
fetcher?: Fetcher<Data, Key> | null,
21
config?: SWRConfiguration<Data, Error>
22
): SWRResponse<Data, Error>;
23
24
// Overloads for different usage patterns
25
function useSWR<Data = any, Error = any>(
26
key: Key,
27
config?: SWRConfiguration<Data, Error>
28
): SWRResponse<Data, Error>;
29
30
function useSWR<Data = any, Error = any>(
31
fetcher: Fetcher<Data, Key>
32
): SWRResponse<Data, Error>;
33
```
34
35
**Usage Examples:**
36
37
```typescript
38
import useSWR from "swr";
39
40
// Basic usage with string key
41
const { data, error, isLoading } = useSWR("/api/user", fetcher);
42
43
// Using array key for multiple parameters
44
const { data } = useSWR(["/api/user", userId], ([url, id]) =>
45
fetch(`${url}/${id}`).then(res => res.json())
46
);
47
48
// Conditional fetching (key is falsy)
49
const { data } = useSWR(
50
shouldFetch ? "/api/data" : null,
51
fetcher
52
);
53
54
// With TypeScript generics
55
interface User {
56
id: number;
57
name: string;
58
email: string;
59
}
60
61
const { data, error } = useSWR<User, Error>("/api/user", fetcher);
62
```
63
64
### SWR Response Object
65
66
The return value from `useSWR` containing data, states, and utilities.
67
68
```typescript { .api }
69
interface SWRResponse<Data, Error> {
70
/** The data returned by the fetcher (undefined if not loaded or error occurred) */
71
data: Data | undefined;
72
/** The error thrown by the fetcher (undefined if no error) */
73
error: Error | undefined;
74
/** Scoped mutate function for this specific key */
75
mutate: KeyedMutator<Data>;
76
/** True when a request or revalidation is loading */
77
isValidating: boolean;
78
/** True when there's no data and no error (initial loading) */
79
isLoading: boolean;
80
}
81
```
82
83
### Key Types
84
85
SWR accepts various key types for different use cases.
86
87
```typescript { .api }
88
type Key =
89
| string
90
| any[]
91
| object
92
| (() => string | any[] | object | null | undefined | false)
93
| null
94
| undefined
95
| false;
96
```
97
98
**Key Examples:**
99
100
```typescript
101
// String key
102
useSWR("/api/user", fetcher);
103
104
// Array key (for multiple parameters)
105
useSWR(["/api/user", userId, "profile"], fetcher);
106
107
// Object key
108
useSWR({ url: "/api/user", method: "GET" }, fetcher);
109
110
// Function key (dynamic)
111
useSWR(() => user ? `/api/user/${user.id}` : null, fetcher);
112
113
// Falsy key (disables fetching)
114
useSWR(null, fetcher); // won't fetch
115
useSWR(false, fetcher); // won't fetch
116
useSWR(undefined, fetcher); // won't fetch
117
```
118
119
### Fetcher Function
120
121
The function responsible for fetching data based on the key.
122
123
```typescript { .api }
124
type Fetcher<Data, SWRKey extends Key> = SWRKey extends () => infer Arg | null | undefined | false
125
? (arg: Arg) => Data | Promise<Data>
126
: SWRKey extends null | undefined | false
127
? never
128
: SWRKey extends infer Arg
129
? (arg: Arg) => Data | Promise<Data>
130
: never;
131
132
// Simplified common case
133
type BareFetcher<Data> = (...args: any[]) => Data | Promise<Data>;
134
```
135
136
**Fetcher Examples:**
137
138
```typescript
139
// Simple fetcher
140
const fetcher = (url: string) => fetch(url).then(res => res.json());
141
142
// Fetcher with error handling
143
const fetcher = async (url: string) => {
144
const res = await fetch(url);
145
if (!res.ok) {
146
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
147
}
148
return res.json();
149
};
150
151
// Fetcher for array keys
152
const fetcher = ([url, params]: [string, object]) =>
153
fetch(url, { method: "POST", body: JSON.stringify(params) })
154
.then(res => res.json());
155
156
// Fetcher with authentication
157
const fetcher = (url: string) =>
158
fetch(url, {
159
headers: {
160
Authorization: `Bearer ${getToken()}`
161
}
162
}).then(res => res.json());
163
```
164
165
### Configuration Options
166
167
Comprehensive configuration options for customizing SWR behavior.
168
169
```typescript { .api }
170
interface SWRConfiguration<Data = any, Error = any> {
171
/** Retry interval on error (default: 5000) */
172
errorRetryInterval?: number;
173
/** Max error retry count (default: 5) */
174
errorRetryCount?: number;
175
/** Timeout to trigger slow event (default: 3000) */
176
loadingTimeout?: number;
177
/** Focus revalidation throttle interval (default: 5000) */
178
focusThrottleInterval?: number;
179
/** Request deduplication interval (default: 2000) */
180
dedupingInterval?: number;
181
/** Polling interval (default: disabled) */
182
refreshInterval?: number;
183
/** Refresh when page is hidden (default: false) */
184
refreshWhenHidden?: boolean;
185
/** Refresh when offline (default: false) */
186
refreshWhenOffline?: boolean;
187
/** Revalidate on window focus (default: true) */
188
revalidateOnFocus?: boolean;
189
/** Revalidate on mount (default: undefined) */
190
revalidateOnMount?: boolean;
191
/** Revalidate on network reconnect (default: true) */
192
revalidateOnReconnect?: boolean;
193
/** Revalidate if data is stale (default: true) */
194
revalidateIfStale?: boolean;
195
/** Retry on error (default: true) */
196
shouldRetryOnError?: boolean | ((err: Error) => boolean);
197
/** Enable React Suspense mode (default: false) */
198
suspense?: boolean;
199
/** Initial data (default: undefined) */
200
fallbackData?: Data;
201
/** Keep previous data during revalidation (default: false) */
202
keepPreviousData?: boolean;
203
/** Custom data comparison function */
204
compare?: (a: Data | undefined, b: Data | undefined) => boolean;
205
/** Check if requests should be paused */
206
isPaused?: () => boolean;
207
/** Middleware functions */
208
use?: Middleware[];
209
/** Success callback */
210
onSuccess?: (data: Data, key: string, config: SWRConfiguration<Data, Error>) => void;
211
/** Error callback */
212
onError?: (err: Error, key: string, config: SWRConfiguration<Data, Error>) => void;
213
/** Custom error retry handler */
214
onErrorRetry?: (
215
err: Error,
216
key: string,
217
config: SWRConfiguration<Data, Error>,
218
revalidate: Revalidator,
219
revalidateOpts: Required<RevalidatorOptions>
220
) => void;
221
/** Slow loading callback */
222
onLoadingSlow?: (key: string, config: SWRConfiguration<Data, Error>) => void;
223
/** Fetcher function */
224
fetcher?: Fetcher<Data, Key> | null;
225
}
226
```
227
228
**Configuration Examples:**
229
230
```typescript
231
// Polling every 5 seconds
232
const { data } = useSWR("/api/stats", fetcher, {
233
refreshInterval: 5000
234
});
235
236
// Disable revalidation on focus
237
const { data } = useSWR("/api/static-data", fetcher, {
238
revalidateOnFocus: false
239
});
240
241
// Custom error retry logic
242
const { data } = useSWR("/api/data", fetcher, {
243
shouldRetryOnError: (error) => error.status !== 404,
244
errorRetryCount: 3,
245
errorRetryInterval: 1000
246
});
247
248
// With Suspense
249
const { data } = useSWR("/api/user", fetcher, {
250
suspense: true
251
});
252
253
// Keep previous data during revalidation
254
const { data } = useSWR(`/api/search?q=${query}`, fetcher, {
255
keepPreviousData: true
256
});
257
```
258
259
### Scoped Mutate Function
260
261
Each `useSWR` instance returns a scoped mutate function for local cache updates.
262
263
```typescript { .api }
264
interface KeyedMutator<Data> {
265
/**
266
* Mutate the cached data for this specific key
267
* @param data - New data, Promise, or function returning new data
268
* @param options - Mutation options or boolean for revalidate
269
* @returns Promise resolving to the new data
270
*/
271
(
272
data?: Data | Promise<Data> | MutatorCallback<Data>,
273
options?: boolean | MutatorOptions<Data>
274
): Promise<Data | undefined>;
275
}
276
277
type MutatorCallback<Data> = (currentData: Data | undefined) => Data | undefined;
278
279
interface MutatorOptions<Data = any> {
280
/** Whether to revalidate after mutation (default: true) */
281
revalidate?: boolean;
282
/** Whether to update cache with mutation result (default: true) */
283
populateCache?: boolean | ((result: Data, currentData: Data | undefined) => Data);
284
/** Data to show optimistically during mutation */
285
optimisticData?: Data | ((currentData: Data | undefined) => Data);
286
/** Whether to rollback on error (default: true) */
287
rollbackOnError?: boolean | ((error: any) => boolean);
288
}
289
```
290
291
**Mutate Examples:**
292
293
```typescript
294
const { data, mutate } = useSWR("/api/user", fetcher);
295
296
// Update with new data
297
await mutate({ ...data, name: "New Name" });
298
299
// Update without revalidation
300
await mutate(newData, false);
301
302
// Optimistic update
303
await mutate(
304
updateUser(newUserData),
305
{
306
optimisticData: { ...data, ...newUserData },
307
rollbackOnError: true
308
}
309
);
310
311
// Function-based update
312
await mutate((currentData) => ({
313
...currentData,
314
lastUpdated: Date.now()
315
}));
316
```
317
318
### Advanced Hook Patterns
319
320
Common patterns for using `useSWR` in complex scenarios.
321
322
**Conditional Fetching:**
323
324
```typescript
325
function UserProfile({ userId }: { userId?: string }) {
326
const { data, error } = useSWR(
327
userId ? `/api/user/${userId}` : null,
328
fetcher
329
);
330
331
if (!userId) return <div>No user selected</div>;
332
if (error) return <div>Error loading user</div>;
333
if (!data) return <div>Loading...</div>;
334
return <div>{data.name}</div>;
335
}
336
```
337
338
**Dependent Requests:**
339
340
```typescript
341
function UserPosts({ userId }: { userId: string }) {
342
const { data: user } = useSWR(`/api/user/${userId}`, fetcher);
343
const { data: posts } = useSWR(
344
user ? `/api/user/${user.id}/posts` : null,
345
fetcher
346
);
347
348
return <div>{posts?.map(post => <div key={post.id}>{post.title}</div>)}</div>;
349
}
350
```
351
352
**Global Error Handling:**
353
354
```typescript
355
function MyComponent() {
356
const { data, error } = useSWR("/api/data", fetcher, {
357
onError: (error, key) => {
358
console.error(`Error fetching ${key}:`, error);
359
// Global error reporting
360
errorReporter.captureException(error);
361
}
362
});
363
}
364
```