SWR

React Hooks for Remote Data Fetching

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.

Using focus revalidation to automatically sync login state between pages.

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.

SWR will make cached pages render much faster, then update the cache with the latest data.

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.

Notice that we also still revalidate, which means our backend is decapitalizing the name and applying different rules that our frontend has forgotten to enforce.

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.

An infinite scroll UI on the ZEIT dashboard, SWR will recover your scroll position.

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.