Lightweight
Backend agnostic
Realtime
JAMstack oriented
Suspense
TypeScript ready
REST compatible
Remote + Local
Introduction
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.
SWR first returns the data from cache (stale), then sends the fetch request (revalidate), and finally comes with the up-to-date data again.
Basic Data Loading
import useSWR from '@zeit/swr'
function Profile () {
const { data, error } = useSWR('/api/user', fetch)
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 the URL of the API. Then key
will be passed to fetch
, which returns the data asynchronously.
useSWR
also returns 2 values: data
and error
, based on the status of the request.
For the detailed API and more examples, visit the repository.
Focus Revalidation
When you re-focus a page or switch between tabs, SWR automatically revalidates data.
This can be useful to immediately synchronize to the latest state. This is helpful for refreshing data in scenarios like stale mobile tabs, or laptops that went to sleep.
Fast Navigation
When navigating through pages or sections inside a system (e.g.: in Next.js), or when pressing the back button, it’s often desirable to load a cached version of the data.
To achieve eventual consistency, SWR will automatically revalidate the data from the origin as soon as data is rendered from the cache.
Local Mutation
SWR scales extremely well because it requires very little effort to write applications that automatically and eventually converge to the most recent remote data.
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. Local mutations are a completely optional way to set a temporary local state that will automatically update on the next revalidation.
Scroll Position Recovery and Pagination
SWR features built-in support for APIs that return data in chunks, with the corresponding UI for “load more”.
And even further, when navigating back to the “load more” list, everything including the scroll position will be recovered automatically.
Custom Data Fetching
SWR uses fetch
by default and assumes a REST-style API call. However, the developer can define any asynchronous function as the fetcher. For example, GraphQL:
import { request } from 'graphql-request'
import useSWR from '@zeit/swr'
const API = 'https://api.graph.cool/simple/v1/movies'
function Profile () {
const { data, error } = useSWR(
`{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}`,
query => request(API, query)
)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>Movie: {data.title}!</div>
}
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.
import useSWR from '@zeit/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'
}
Suspense
You can also use SWR Hooks with React Suspense. Just enable suspense: true
in the SWR config and everything will work smoothly.
import { Suspense } from 'react'
import useSWR from '@zeit/swr'
function Profile () {
const { data } = useSWR(
'/api/user',
fetch,
{ suspense: true }
)
return <div>hello, {data.name}</div>
}
function App () {
return (
<Suspense fallback={<div>loading...</div>}>
<Profile/>
</Suspense>
)
}
Visit the GitHub Repository for more examples and documentation.