or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cache-management.mdcore-data-fetching.mdglobal-configuration.mdimmutable-data.mdindex.mdinfinite-loading.mdmutations.mdsubscriptions.md

core-data-fetching.mddocs/

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

```