-## Intro
+## Introduction
+
+[swr.now.sh](https://swr.now.sh)
SWR is a React Hooks library for remote data fetching.
-The name “**SWR**” is derived from `stale-while-revalidate`, a HTTP cache invalidation strategy popularized by [RFC 5861](https://tools.ietf.org/html/rfc5861).
+The name “**SWR**” is derived from `stale-while-revalidate`, a HTTP cache invalidation strategy popularized by [RFC 5861](https://tools.ietf.org/html/rfc5861).
**SWR** first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.
It features:
@@ -37,11 +35,11 @@ It features:
- Suspense mode
- Minimal API
-With SWR, components will get a stream of data updates constantly and automatically, Thus, the UI will be always fast and reactive.
+...and a lot more.
-## Quick Start
+With SWR, components will get **a stream of data updates constantly and automatically**. Thus, the UI will be always **fast** and **reactive**.
-To install, run `yarn add swr` or `npm install swr` in your React project.
+## Quick Start
```js
import useSWR from 'swr'
@@ -56,7 +54,7 @@ function Profile () {
```
In this example, the React Hook `useSWR` accepts a `key` and a `fetcher` function.
-`key` is a unique identifier of the data, normally a URL of the API. And the `fetcher` accepts
+`key` is a unique identifier of the request, normally the URL of the API. And the `fetcher` accepts
`key` as its parameter and returns the data asynchronously.
`useSWR` also returns 2 values: `data` and `error`. When the request (fetcher) is not yet finished,
@@ -66,209 +64,276 @@ of `fetcher` and rerenders the component.
Note that `fetcher` can be any asynchronous function, so you can use your favourite data-fetching
library to handle that part.
----
+Check out [swr.now.sh](https://swr.now.sh) for more demos of SWR.
-- API
- - [`useSWR`](#useswr)
- - [`SWRConfig`](#swrconfig)
- - [`mutate`](#mutate)
- - [`trigger`](#trigger)
-- Examples
- - [Suspense Mode](#suspense-mode)
- - [Subscription (e.g.: socket.io)](#subscription-eg-socketio)
- - [Dependent Fetching](#dependent-fetching)
+## Usage
-## API
+Inside your React project directory, run the following:
-### `useSWR`
+```
+yarn add swr
+```
+
+Or with npm:
+
+```
+npm install swr
+```
+
+### API
```js
-const {
- data, // data for the given key (or undefined)
- error, // error (or undefined)
- isValidating, // if the request is loading
- revalidate // function to trigger a validate manually
-} = useSWR(
- key, // a unique key for the data (or a function, see below)
- fetcher, // Promise returning function to load your data
- swrOptions? = {
- suspense: false, // enabled React Suspense mode
- revalidateOnFocus: true, // auto revalidate when window gets focused
- refreshWhenHidden: false, // refresh while the window is invisible
- shouldRetryOnError: true, // retry when fetcher has an error
- refreshInterval: 0, // polling interval (disabled by default)
- errorRetryInterval: 5000, // error retry interval (10s on slow network)
- focusThrottleInterval: 5000, // keep focus revalidate requests in a time window
- dedupingInterval: 2000, // deduping requests
- loadingTimeout: 3000, // timeout for triggering the onLoadingSlow event
-
- onLoadingSlow, // event handlers
- onSuccess,
- onError,
- onErrorRetry,
-
- fetcher // default fetcher function
- }
-)
+const { data, error, isValidating, revalidate } = useSWR(key, fetcher, options)
```
-#### `key` as a function
+#### Parameters
+
+- `key`: a unique key string for the request (or a function / null) [(advanced usage)](#conditional-fetching)
+- `fetcher`: (_optional_) a Promise returning function to fetch your data [(details)](#data-fetching)
+- `options`: (_optional_) an object of options for this SWR hook
-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.
+#### Return Values
+- `data`: data for the given key resolved by `fetcher` (or undefined if not loaded)
+- `error`: error thrown by `fetcher` (or undefined)
+- `isValidating`: if there's a request or revalidation loading
+- `revalidate`: function to trigger the validation manually
+
+#### Options
+
+- `suspense = false`: enable React Suspense mode [(details)](#suspense-mode)
+- `fetcher = undefined`: the default fetcher function
+- `revalidateOnFocus = true`: auto revalidate when window gets focused
+- `refreshInterval = 0`: polling interval (disabled by default)
+- `refreshWhenHidden = false`: polling when the window is invisible (if `refreshInterval` is enabled)
+- `shouldRetryOnError = true`: retry when fetcher has an error [(details)](#error-retries)
+- `dedupingInterval = 2000`: dedupe requests with the same key in this time span
+- `focusThrottleInterval = 5000`: only revalidate once during a time span
+- `loadingTimeout = 3000`: timeout to trigger the onLoadingSlow event
+- `errorRetryInterval = 5000`: error retry interval [(details)](#error-retries)
+- `onLoadingSlow`: callback function when a request takes too long to load (`loadingTimeout`)
+- `onSuccess`: callback function when a request finishs successfully
+- `onError`: callback function when a request returns an error
+- `onErrorRetry`: handler for [error retry](#error-retries)
+
+When under a slow network (2G, <= 70Kbps), `errorRetryInterval` will be 10s, and
+`loadingTimeout` will be 5s by default.
+
+You can also use [global configuration](#global-configuration) to provide default options.
+
+## Examples
+
+- [Global Configuration](#global-configuration)
+- [Data Fetching](#data-fetching)
+- [Conditional Fetching](#conditional-fetching)
+- [Dependent Fetching](#dependent-fetching)
+- [Manually Revalidate](#manually-revalidate)
+- [Local Mutation](#local-mutation)
+- [Suspense Mode](#suspense-mode)
+- [Error Retries](#error-retries)
+
+### Global Configuration
+
+You can use `SWRConfig` to provide global configurations (`options`) for all SWR hooks.
+
+In this example, all `useSWR` hooks will use the same fetcher provided to load JSON data, and refresh every 3 seconds (except the user API):
```js
-// key returns a falsy value
-const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
+import useSWR, { SWRConfig } from 'swr'
-// key throws an error when user.id is not defined
-const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
+function Dashboard () {
+ const { data: events } = useSWR('/api/events')
+ const { data: projects } = useSWR('/api/projects')
+ const { data: user } = useSWR('/api/user', { refreshInterval: 0 })
+ // ...
+}
+
+function App () {
+ return (
+ fetch(...args).then(res => res.json())
+ }}
+ >
+
+
+ )
+}
```
-### `SWRConfig`
+### Data Fetching
-A context to provide global configurations (`swrOptions`) for SWR.
+`fetcher` is a function **accepts the `key`** of SWR, and returns a value or a Promise.
+You can use any library you to handle data fetching, for example:
```js
-import useSWR, { SWRConfig } from 'swr'
+import fetch from 'unfetch'
+
+const fetcher = url => fetch(url).then(r => r.json())
function App () {
- // all the SWRs inside will use `refreshInterval: 1000`
- // and the native `fetch` implementation
- return fetch(...args).then(res => res.json())
- }}>
-
-
+ const { data } = useSWR('/api/data', fetcher)
+ // ...
}
+```
-function Profile () {
- const { data, error } = useSWR('/api/user')
+Or using GraphQL:
+```js
+import { request } from 'graphql-request'
+
+const API = 'https://api.graph.cool/simple/v1/movies'
+const fetcher = query => request(API, query)
+
+function App () {
+ const { data, error } = useSWR(
+ `{
+ Movie(title: "Inception") {
+ releaseDate
+ actors {
+ name
+ }
+ }
+ }`,
+ fetcher
+ )
// ...
}
```
-### `mutate`
+Note that `fetcher` can be skipped from the parameters if it's provided gloablly.
-With `mutate`, you can update your local data programmatically, while
-revalidating and finally replace it.
+### Conditional Fetching
+
+Use `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.
```js
-import useSWR, { mutate } from 'swr'
+// conditionally fetch
+const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
-function Profile () {
- const { data } = useSWR('/api/user', fetcher)
+// ...or return a falsy value
+const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
+
+// ... or throw an error when user.id is not defined
+const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
+```
+
+### Dependent Fetching
+
+SWR 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.
+
+```js
+function MyProjects () {
+ const { data: user } = useSWR('/api/user')
+ const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
+ // When passing a function, SWR will use the
+ // return value as `key`. If the function throws,
+ // SWR will know that some dependencies are not
+ // ready. In this case it is `user`.
- return
-
My name is {data.name}.
-
-
+ if (!projects) return 'loading...'
+ return 'You have ' + projects.length + ' projects'
}
```
-### `trigger`
+### Manually Revalidate
You can broadcast a revalidation message to all SWR data inside any component by calling
`trigger(key)`.
+This example shows how to automatically refetch the login info (e.g.: inside ``)
+when the user clicks the “Logout” button.
+
```js
import useSWR, { trigger } from 'swr'
function App () {
- return
-
-
-
+ return (
+
+
+
+
+ )
}
```
-## Examples
+### Local Mutation
-### Suspense Mode
+In many cases, applying local mutations to data is a good way to make changes
+feel faster — no need to wait for the remote source of data.
-You can enable the `suspense` option to use `useSWR` with React Suspense.
+With `mutate`, you can update your local data programmatically, while
+revalidating and finally replace it with the latest data.
```js
-import { Suspense } from 'react'
-import useSWR from 'swr'
+import useSWR, { mutate } from 'swr'
function Profile () {
- const { data } = useSWR('/api/user', fetcher, { suspense: true })
- return
+ )
}
```
-### Subscription (e.g.: socket.io)
+### Suspense Mode
-You can use SWR with socket.io (generally any subscription pattern) like this:
+You can enable the `suspense` option to use SWR with React Suspense:
```js
-// fetch-data.js
-
-import { mutate } from 'swr'
-
-let latestData = null
+import { Suspense } from 'react'
+import useSWR from 'swr'
-// setup ws and broadcast to all SWRs
-...
-socket.on('data', data => {
- latestData = data
- mutate('/api/data', data, false)
-})
+function Profile () {
+ const { data } = useSWR('/api/user', fetcher, { suspense: true })
+ return
hello, {data.name}
+}
-export default () => latestData
+function App () {
+ return (
+ loading...}>
+
+
+ )
+}
```
-and your component:
+Note 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.
-```js
-import useSWR from 'swr'
-import fetchData from './fetch-data'
+### Error Retries
-function App () {
- const { data } = useSWR('/api/data', fetchData)
- // ...
-}
-```
+By default, SWR uses the [exponential backoff algorithm](https://en.wikipedia.org/wiki/Exponential_backoff) to handle error retries.
+You can read more from the source code.
-### Dependent Fetching
-SWR 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.
+It's also possible to override the behavior:
```js
-import useSWR from 'swr'
-
-function MyProjects () {
- const { data: user } = useSWR('/api/user')
- const { data: projects } = useSWR(
- () => '/api/projects?uid=' + user.id
- )
- // When passing a function, SWR will use the
- // return value as `key`. If the function throws,
- // SWR will know that some dependencies are not
- // ready. In this case it is `user`.
+useSWR(key, fetcher, {
+ onErrorRetry: (error, key, option, revalidate, { retryCount }) => {
+ if (retryCount >= 10) return
+ if (error.status === 404) return
- if (!projects) return 'loading...'
- return 'You have ' + projects.length + ' projects'
-}
+ // retry after 5 seconds
+ setTimeout(() => revalidate({ retryCount: retryCount + 1 }), 5000)
+ }
+})
```
## Authors