Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve readme #73

Merged
merged 4 commits into from
Nov 4, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this code be inside the examples folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sergiodxa Yeah, I think we can add this model to your localStorage example using the storage event. So we can sync the data without focusing on the other window.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting up socket.io for an example might be a bit overkill IMO.


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