Stale While Revalidate (SWR)
SWR (Stale-While-Revalidate) is a data-fetching strategy used in web programming that optimizes user experience by serving stale (cached) data instantly while updating it in the background. This approach is popular in frameworks like Next.js to handle data fetching for React components, helping to achieve faster and more responsive applications.
SWR in Web Programming
In a general web context, SWR is a caching and revalidation strategy where:
- Stale data (cached) is served immediately upon request, reducing load times and providing instant feedback to the user.
- While revalidating, a background fetch is triggered to update the cached data if it's outdated or missing. Once updated, the cache refreshes, and the latest data is available for future requests.
The SWR pattern is common in situations where data does not change frequently or where the initial data doesn't need to be real-time accurate, such as dashboards, profiles, and product listings.
SWR in Next.js with the swr
Library
In Next.js, SWR (opens in a new tab) is implemented via the swr
library (opens in a new tab), developed by Vercel (the creators of Next.js). The swr
library provides an easy way to manage data fetching with React hooks, using the SWR caching strategy under the hood. Here’s how it works in Next.js:
Installation
npm install swr
Usage
The API of useSWR
is:
const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options)
The key
param in useSWR(key, fetcher, options)
it actually is a key.
It is a unique string that represents the data that is being fetched. If the key changes, the data will be refetched.
The fetcher
function is a function that fetches the data.
It should return a promise that resolves to the data, that is why we use
fetch(catURL).then((res) => res.json())
.
The options
object is an optional object (opens in a new tab) that can be used to configure the behavior of the SWR hook.
Here we set revalidateOnFocus
to false
to avoid revalidating the data when the window regains focus.
The return Values are:
data
: data for the given key resolved by fetcher (orundefined
if not loaded)error
: error thrown by fetcher (orundefined
)isLoading
: if there's an ongoing request and no "loaded data". Fallback data and previous data are not considered "loaded data"isValidating
: if there's a request or revalidation loadingmutate(data?, options?)
: function to mutate the cached data (details (opens in a new tab))
More information can be found here (opens in a new tab).
Benefits of using SWR in Next.js include:
- Automatic Caching: Caches the result of each request and uses it for subsequent renders.
- Real-time Updates: Background revalidation keeps data up-to-date without blocking UI.
- Error Handling and Loading States: Handles error and loading states by default, simplifying code.
Example of usage of SWR in Nextra
Here is the code for a <Teams>
component that shows the GitHub teams in a GitHub organization.
It relies on an Next.js API route /pages/api/getteams (opens in a new tab) to fetch the data.
import styles from './counters.module.css'
import useSWR from 'swr'
import { Link } from 'nextra-theme-docs';
const fetcher = (...args) => fetch(...args).then((res) => res.json())
export default function Teams() {
const { data, error } = useSWR('/api/getteams', fetcher)
if (error) return <div>Failed to load {error}</div>
if (!data) return <div>Loading...</div>
if (data?.teams?.length) return (
<div>
<p>{data.teams.length} Teams</p>
<ul className={styles.uList}>
{
data.teams.map(t => (
<li key={t.name}>
<Link href={t.url}>{t.name}</Link>
<span> - </span>
<Link href={t.url+"/repositories"}>Repos</Link>
</li>)
)
}
</ul>
</div>
)
return 'Sign in to see your teams';
}