UNPKG

10.8 kBMarkdownView Raw
1[![SWR](https://assets.zeit.co/image/upload/v1572289618/swr/banner.png)](https://swr.now.sh)
2
3<p align="center">
4 <a aria-label="ZEIT logo" href="https://github.com/zeit">
5 <img src="https://img.shields.io/badge/MADE%20BY%20ZEIT-000000.svg?logo=ZEIT&labelColor=000000&logoWidth=12">
6 </a>
7 <a aria-label="NPM version" href="https://www.npmjs.com/package/swr">
8 <img alt="" src="https://img.shields.io/npm/v/swr">
9 </a>
10 <a aria-label="Package size" href="https://bundlephobia.com/result?p=swr">
11 <img alt="" src="https://img.shields.io/bundlephobia/minzip/swr">
12 </a>
13 <a aria-label="License" href="https://github.com/zeit/swr/blob/master/LICENSE">
14 <img alt="" src="https://img.shields.io/npm/l/swr">
15 </a>
16</p>
17
18## Introduction
19
20[swr.now.sh](https://swr.now.sh)
21
22SWR is a React Hooks library for remote data fetching.
23
24The name “**SWR**” is derived from `stale-while-revalidate`, a HTTP cache invalidation strategy popularized by [RFC 5861](https://tools.ietf.org/html/rfc5861).
25**SWR** first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.
26
27It features:
28- Transport and protocol agnostic data fetching
29- Fast page navigation
30- Revalidation on focus
31- Interval polling
32- Local mutation
33- Pagination
34- TypeScript ready
35- Suspense mode
36- Minimal API
37
38...and a lot more.
39
40With SWR, components will get **a stream of data updates constantly and automatically**. Thus, the UI will be always **fast** and **reactive**.
41
42## Quick Start
43
44```js
45import useSWR from 'swr'
46
47function Profile () {
48 const { data, error } = useSWR('/api/user', fetcher)
49
50 if (error) return <div>failed to load</div>
51 if (!data) return <div>loading...</div>
52 return <div>hello {data.name}!</div>
53}
54```
55
56In this example, the React Hook `useSWR` accepts a `key` and a `fetcher` function.
57`key` is a unique identifier of the request, normally the URL of the API. And the `fetcher` accepts
58`key` as its parameter and returns the data asynchronously.
59
60`useSWR` also returns 2 values: `data` and `error`. When the request (fetcher) is not yet finished,
61`data` will be `undefined`. And when we get a response, it sets `data` and `error` based on the result
62of `fetcher` and rerenders the component.
63
64Note that `fetcher` can be any asynchronous function, so you can use your favourite data-fetching
65library to handle that part.
66
67Check out [swr.now.sh](https://swr.now.sh) for more demos of SWR.
68
69## Usage
70
71Inside your React project directory, run the following:
72
73```
74yarn add swr
75```
76
77Or with npm:
78
79```
80npm install swr
81```
82
83### API
84
85```js
86const { data, error, isValidating, revalidate } = useSWR(key, fetcher, options)
87```
88
89#### Parameters
90
91- `key`: a unique key string for the request (or a function / null) [(advanced usage)](#conditional-fetching)
92- `fetcher`: (_optional_) a Promise returning function to fetch your data [(details)](#data-fetching)
93- `options`: (_optional_) an object of options for this SWR hook
94
95#### Return Values
96- `data`: data for the given key resolved by `fetcher` (or undefined if not loaded)
97- `error`: error thrown by `fetcher` (or undefined)
98- `isValidating`: if there's a request or revalidation loading
99- `revalidate`: function to trigger the validation manually
100
101#### Options
102
103- `suspense = false`: enable React Suspense mode [(details)](#suspense-mode)
104- `fetcher = undefined`: the default fetcher function
105- `revalidateOnFocus = true`: auto revalidate when window gets focused
106- `refreshInterval = 0`: polling interval (disabled by default)
107- `refreshWhenHidden = false`: polling when the window is invisible (if `refreshInterval` is enabled)
108- `shouldRetryOnError = true`: retry when fetcher has an error [(details)](#error-retries)
109- `dedupingInterval = 2000`: dedupe requests with the same key in this time span
110- `focusThrottleInterval = 5000`: only revalidate once during a time span
111- `loadingTimeout = 3000`: timeout to trigger the onLoadingSlow event
112- `errorRetryInterval = 5000`: error retry interval [(details)](#error-retries)
113- `onLoadingSlow`: callback function when a request takes too long to load (`loadingTimeout`)
114- `onSuccess`: callback function when a request finishs successfully
115- `onError`: callback function when a request returns an error
116- `onErrorRetry`: handler for [error retry](#error-retries)
117
118When under a slow network (2G, <= 70Kbps), `errorRetryInterval` will be 10s, and
119`loadingTimeout` will be 5s by default.
120
121You can also use [global configuration](#global-configuration) to provide default options.
122
123## Examples
124
125- [Global Configuration](#global-configuration)
126- [Data Fetching](#data-fetching)
127- [Conditional Fetching](#conditional-fetching)
128- [Dependent Fetching](#dependent-fetching)
129- [Manually Revalidate](#manually-revalidate)
130- [Local Mutation](#local-mutation)
131- [Suspense Mode](#suspense-mode)
132- [Error Retries](#error-retries)
133
134### Global Configuration
135
136You can use `SWRConfig` to provide global configurations (`options`) for all SWR hooks.
137
138In this example, all `useSWR` hooks will use the same fetcher provided to load JSON data, and refresh every 3 seconds (except the user API):
139
140```js
141import useSWR, { SWRConfig } from 'swr'
142
143function Dashboard () {
144 const { data: events } = useSWR('/api/events')
145 const { data: projects } = useSWR('/api/projects')
146 const { data: user } = useSWR('/api/user', { refreshInterval: 0 })
147 // ...
148}
149
150function App () {
151 return (
152 <SWRConfig
153 value={{
154 refreshInterval: 3000,
155 fetcher: (...args) => fetch(...args).then(res => res.json())
156 }}
157 >
158 <Dashboard />
159 </SWRConfig>
160 )
161}
162```
163
164### Data Fetching
165
166`fetcher` is a function **accepts the `key`** of SWR, and returns a value or a Promise.
167You can use any library you to handle data fetching, for example:
168
169```js
170import fetch from 'unfetch'
171
172const fetcher = url => fetch(url).then(r => r.json())
173
174function App () {
175 const { data } = useSWR('/api/data', fetcher)
176 // ...
177}
178```
179
180Or using GraphQL:
181```js
182import { request } from 'graphql-request'
183
184const API = 'https://api.graph.cool/simple/v1/movies'
185const fetcher = query => request(API, query)
186
187function App () {
188 const { data, error } = useSWR(
189 `{
190 Movie(title: "Inception") {
191 releaseDate
192 actors {
193 name
194 }
195 }
196 }`,
197 fetcher
198 )
199 // ...
200}
201```
202
203Note that `fetcher` can be skipped from the parameters if it's provided gloablly.
204
205### Conditional Fetching
206
207Use `null` or pass a function as the `key` to `useSWR` to conditionally fetch data. If the functions throws an error or returns a falsy value, SWR will cancel the request.
208
209```js
210// conditionally fetch
211const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
212
213// ...or return a falsy value
214const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
215
216// ... or throw an error when user.id is not defined
217const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
218```
219
220### Dependent Fetching
221
222SWR also allows you to fetch data that depends on other data. It ensures the maximum possible parallelism (avoiding waterfalls), as well as serial fetching when a piece of dynamic data is required for the next data fetch to happen.
223
224```js
225function MyProjects () {
226 const { data: user } = useSWR('/api/user')
227 const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
228 // When passing a function, SWR will use the
229 // return value as `key`. If the function throws,
230 // SWR will know that some dependencies are not
231 // ready. In this case it is `user`.
232
233 if (!projects) return 'loading...'
234 return 'You have ' + projects.length + ' projects'
235}
236```
237
238### Manually Revalidate
239
240You can broadcast a revalidation message to all SWR data inside any component by calling
241`trigger(key)`.
242
243This example shows how to automatically refetch the login info (e.g.: inside `<Profile/>`)
244when the user clicks the “Logout” button.
245
246```js
247import useSWR, { trigger } from 'swr'
248
249function App () {
250 return (
251 <div>
252 <Profile />
253 <button onClick={() => {
254 // set the cookie as expired
255 document.cookie = 'token=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'
256
257 // tell all SWRs with this key to revalidate
258 trigger('/api/user')
259 }}>
260 Logout
261 </button>
262 </div>
263 )
264}
265```
266
267### Local Mutation
268
269In many cases, applying local mutations to data is a good way to make changes
270feel faster — no need to wait for the remote source of data.
271
272With `mutate`, you can update your local data programmatically, while
273revalidating and finally replace it with the latest data.
274
275```js
276import useSWR, { mutate } from 'swr'
277
278function Profile () {
279 const { data } = useSWR('/api/user', fetcher)
280
281 return (
282 <div>
283 <h1>My name is {data.name}.</h1>
284 <button onClick={async () => {
285 const newName = data.name.toUpperCase()
286 // send a request to the API to update the data
287 await requestUpdateUsername(newName)
288 // update the local data immediately and revalidate (refetch)
289 mutate('/api/user', { ...data, name: newName })
290 }}>Uppercase my name!</button>
291 </div>
292 )
293}
294```
295
296### Suspense Mode
297
298You can enable the `suspense` option to use SWR with React Suspense:
299
300```js
301import { Suspense } from 'react'
302import useSWR from 'swr'
303
304function Profile () {
305 const { data } = useSWR('/api/user', fetcher, { suspense: true })
306 return <div>hello, {data.name}</div>
307}
308
309function App () {
310 return (
311 <Suspense fallback={<div>loading...</div>}>
312 <Profile/>
313 </Suspense>
314 )
315}
316```
317
318Note in Suspense mode, `data` is always the fetch response (so you don't need to check if it's `undefined`). But if there's an error occurred, you need to use an [error boundary](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors) to catch it.
319
320### Error Retries
321
322By default, SWR uses the [exponential backoff algorithm](https://en.wikipedia.org/wiki/Exponential_backoff) to handle error retries.
323You can read more from the source code.
324
325It's also possible to override the behavior:
326
327```js
328useSWR(key, fetcher, {
329 onErrorRetry: (error, key, option, revalidate, { retryCount }) => {
330 if (retryCount >= 10) return
331 if (error.status === 404) return
332
333 // retry after 5 seconds
334 setTimeout(() => revalidate({ retryCount: retryCount + 1 }), 5000)
335 }
336})
337```
338
339## Authors
340- Shu Ding ([@shuding_](https://twitter.com/shuding_)) – [ZEIT](https://zeit.co)
341- Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) – [ZEIT](https://zeit.co)
342- Joe Haddad ([@timer150](https://twitter.com/timer150)) - [ZEIT](https://zeit.co)
343- Paco Coursey ([@pacocoursey](https://twitter.com/pacocoursey)) - [ZEIT](https://zeit.co)
344
345Thanks to Ryan Chen for providing the awesome `swr` npm package name!
346
347## License
348The MIT License.