Skip to content

Commit

Permalink
Improve readme (#73)
Browse files Browse the repository at this point in the history
* improve the documentation about `fetch`

* add TOC and examples

* update badges

* Add section about key as a function
  • Loading branch information
shuding committed Nov 4, 2019
1 parent 9ae313d commit a2d700b
Showing 1 changed file with 106 additions and 17 deletions.
123 changes: 106 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

<p align="center">
<a aria-label="ZEIT logo" href="https://github.com/zeit">
<img src="https://img.shields.io/badge/MADE%20BY%20ZEIT-000000.svg?style=for-the-badge&logo=ZEIT&labelColor=000000&logoWidth=20">
<img src="https://img.shields.io/badge/MADE%20BY%20ZEIT-000000.svg?logo=ZEIT&labelColor=000000&logoWidth=12">
</a>
<a aria-label="NPM version" href="https://www.npmjs.com/package/swr">
<img alt="" src="https://img.shields.io/npm/v/swr?style=for-the-badge&labelColor=000000">
<img alt="" src="https://img.shields.io/npm/v/swr">
</a>
<a aria-label="Package size" href="https://bundlephobia.com/result?p=swr">
<img alt="" src="https://img.shields.io/bundlephobia/minzip/swr">
</a>
<a aria-label="License" href="https://github.com/zeit/swr/blob/master/LICENSE">
<img alt="" src="https://img.shields.io/npm/l/swr?style=for-the-badge&labelColor=000000">
<img alt="" src="https://img.shields.io/npm/l/swr">
</a>
</p>

Expand All @@ -38,29 +41,43 @@ With SWR, components will get a stream of data updates constantly and automatica

## Quick Start

To install, run `yarn add swr` or `npm install swr` in your React project.

```js
import useSWR from 'swr'

function Profile () {
const { data, error } = useSWR('/api/user', fetch)
const { data, error } = useSWR('/api/user', fetcher)

if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
```

In this example, the React Hook `useSWR` accepts a `key` and a `fetch` function.
`key` is a unique identifier of the data, normally a URL of the API. And the `fetch` accepts
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` as its parameter and returns the data asynchronously.

`useSWR` also returns 2 values: `data` and `error`. When the request (fetch) is not yet finished,
`useSWR` also returns 2 values: `data` and `error`. When the request (fetcher) is not yet finished,
`data` will be `undefined`. And when we get a response, it sets `data` and `error` based on the result
of `fetch` and rerenders the component.
of `fetcher` and rerenders the component.

Note that `fetch` can be any asynchronous function, so you can use your favourite data-fetching
Note that `fetcher` can be any asynchronous function, so you can use your favourite data-fetching
library to handle that part.

---

- 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)

## API

### `useSWR`
Expand All @@ -72,13 +89,13 @@ const {
isValidating, // if the request is loading
revalidate // function to trigger a validate manually
} = useSWR(
key, // a unique key for the data
fn, // Promise returning function to fetch your data
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 fetch has an error
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
Expand All @@ -90,11 +107,23 @@ const {
onError,
onErrorRetry,

fetcher // default fetcher function (same as `fn`)
fetcher // default fetcher function
}
)
```
#### `key` as a function
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
// key returns a falsy value
const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)

// key throws an error when user.id is not defined
const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
```
### `SWRConfig`
A context to provide global configurations (`swrOptions`) for SWR.
Expand All @@ -104,13 +133,17 @@ import useSWR, { SWRConfig } from 'swr'

function App () {
// all the SWRs inside will use `refreshInterval: 1000`
return <SWRConfig value={{ refreshInterval: 1000 }}>
// and the native `fetch` implementation
return <SWRConfig value={{
refreshInterval: 1000,
fetcher: (...args) => fetch(...args).then(res => res.json())
}}>
<Profile/>
</SWRConfig>
}

function Profile () {
const { data, error } = useSWR('/api/user', fetch)
const { data, error } = useSWR('/api/user')
// ...
}
```
Expand All @@ -124,7 +157,7 @@ revalidating and finally replace it.
import useSWR, { mutate } from 'swr'

function Profile () {
const { data } = useSWR('/api/user', fetch)
const { data } = useSWR('/api/user', fetcher)

return <div>
<h1>My name is {data.name}.</h1>
Expand Down Expand Up @@ -162,6 +195,8 @@ function App () {
}
```
## Examples
### Suspense Mode
You can enable the `suspense` option to use `useSWR` with React Suspense.
Expand All @@ -171,7 +206,7 @@ import { Suspense } from 'react'
import useSWR from 'swr'

function Profile () {
const { data } = useSWR('/api/user', fetch, { suspense: true })
const { data } = useSWR('/api/user', fetcher, { suspense: true })
return <div>hello, {data.name}</div>
}

Expand All @@ -182,6 +217,60 @@ function App () {
}
```
### Subscription (e.g.: socket.io)
You can use SWR with socket.io (generally any subscription pattern) like this:
```js
// fetch-data.js

import { mutate } from 'swr'

let latestData = null

// setup ws and broadcast to all SWRs
...
socket.on('data', data => {
latestData = data
mutate('/api/data', data, false)
})

export default () => latestData
```
and your component:
```js
import useSWR from 'swr'
import fetchData from './fetch-data'

function App () {
const { data } = useSWR('/api/data', fetchData)
// ...
}
```
### 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.
```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`.

if (!projects) return 'loading...'
return 'You have ' + projects.length + ' projects'
}
```
## Authors
- Shu Ding ([@shuding_](https://twitter.com/shuding_)) – [ZEIT](https://zeit.co)
- Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) – [ZEIT](https://zeit.co)
Expand Down

0 comments on commit a2d700b

Please sign in to comment.