### Install SWR via bun
Source: https://swr.vercel.app/docs/getting-started
Run this command in your React project directory to install SWR using bun.
```bash
bun add swr
```
--------------------------------
### Install SWR via npm
Source: https://swr.vercel.app/docs/getting-started
Run this command in your React project directory to install SWR using npm.
```bash
npm i swr
```
--------------------------------
### Install SWR via pnpm
Source: https://swr.vercel.app/docs/getting-started
Run this command in your React project directory to install SWR using pnpm.
```bash
pnpm add swr
```
--------------------------------
### Install SWR via yarn
Source: https://swr.vercel.app/docs/getting-started
Run this command in your React project directory to install SWR using yarn.
```bash
yarn add swr
```
--------------------------------
### Cursor Based Paginated API Example
Source: https://swr.vercel.app/docs/pagination
Example of using useSWRInfinite with a cursor-based API. Includes the API response format and the updated getKey function.
```plaintext
GET /users?cursor=123&limit=10
{
data: [
{ name: 'Alice' },
{ name: 'Bob' },
{ name: 'Cathy' },
...
],
nextCursor: 456
}
```
```jsx
const getKey = (pageIndex, previousPageData) => {
// reached the end
if (previousPageData && !previousPageData.data) return null
// first page, we don't have `previousPageData`
if (pageIndex === 0) return `/users?limit=10`
// add the cursor to the API endpoint
return `/users?cursor=${previousPageData.nextCursor}&limit=10`
}
```
--------------------------------
### Global Setup with SWRConfig
Source: https://swr.vercel.app/docs/advanced/react-native
Wrap the app in SWRConfig to preconfigure all SWR settings globally. The value prop accepts an object with configuration options.
```jsx
```
--------------------------------
### Index Based Paginated API Example
Source: https://swr.vercel.app/docs/pagination
Example of using useSWRInfinite with an index-based API. Includes the API response format and the React component implementation.
```plaintext
GET /users?page=0&limit=10
[
{ name: 'Alice', ... },
{ name: 'Bob', ... },
{ name: 'Cathy', ... },
...
]
```
```jsx
// A function to get the SWR key of each page,
// its return value will be accepted by `fetcher`.
// If `null` is returned, the request of that page won't start.
const getKey = (pageIndex, previousPageData) => {
if (previousPageData && !previousPageData.length) return null // reached the end
return `/users?page=${pageIndex}&limit=10` // SWR key
}
function App () {
const { data, size, setSize } = useSWRInfinite(getKey, fetcher)
if (!data) return 'loading'
// We can now calculate the number of all users
let totalUsers = 0
for (let i = 0; i < data.length; i++) {
totalUsers += data[i].length
}
return
{totalUsers} users listed
{data.map((users, index) => {
// `data` is an array of each page's API response.
return users.map(user =>
{user.name}
)
})}
}
```
--------------------------------
### WebSocket subscription example
Source: https://swr.vercel.app/docs/subscription
Example of using useSWRSubscription to subscribe to a WebSocket data source. It handles messages and errors, and closes the socket on cleanup.
```tsx
import useSWRSubscription from 'swr/subscription'
function App() {
const { data, error } = useSWRSubscription('ws://...', (key, { next }) => {
const socket = new WebSocket(key)
socket.addEventListener('message', (event) => next(null, event.data))
socket.addEventListener('error', (event) => next(event.error))
return () => socket.close()
})
if (error) return
failed to load
if (!data) return
loading...
return
hello {data}!
}
```
--------------------------------
### Firestore subscription example
Source: https://swr.vercel.app/docs/subscription
Example of using useSWRSubscription to subscribe to a Firestore data source. It listens to a reference and updates the view count.
```tsx
import useSWRSubscription from 'swr/subscription'
function Post({ id }) {
const { data } = useSWRSubscription(['views', id], ([_, postId], { next }) => {
const ref = firebase.database().ref('views/' + postId)
ref.on('value',
snapshot => next(null, snapshot.data()),
err => next(err)
)
return () => ref.off()
})
return Your post has {data} views!
}
```
--------------------------------
### initFocus with AppState
Source: https://swr.vercel.app/docs/advanced/react-native
Example of initFocus using React Native's AppState to detect when the app becomes active. The callback is triggered when transitioning from inactive or background to active, and the subscription is cleaned up on unmount.
```jsx
import { AppState } from 'react-native'
// ...
new Map(),
isVisible: () => { return true },
initFocus(callback) {
let appState = AppState.currentState
const onAppStateChange = (nextAppState) => {
/* If it's resuming from inactive or background mode to active */
if (appState.match(/inactive|background/) && nextAppState === 'active') {
callback()
}
appState = nextAppState
}
// Subscribe to the app state change events
const subscription = AppState.addEventListener('change', onAppStateChange)
return () => {
subscription.remove()
}
}
}}
>
```
--------------------------------
### HTML rel="preload" for Top-Level Requests
Source: https://swr.vercel.app/docs/prefetching
Use a link tag in the HTML head to prefetch data natively when the HTML loads, before JavaScript starts.
```html
```
--------------------------------
### Console output when only using data
Source: https://swr.vercel.app/docs/advanced/performance
Shows the console output from the previous example when only the data state is used. There are only two re-renders: the initial render and after the retry succeeds.
```js
// console.log(data)
undefined // => hydration / initial render
Data // => end retrying, get the data
```
--------------------------------
### Prefetch Data in Server Components with preload and cacheData
Source: https://swr.vercel.app/docs/with-nextjs
In React Server Components (RSC), start fetching with preload and pass the returned data to the client component tree through the cacheData option of . The preload calls start fetching immediately, so requests run in parallel without being awaited in the layout.
```tsx
import { preload, SWRConfig } from 'swr'
export default async function Layout({ children }: { children: React.ReactNode }) {
const cacheData = {
...preload('/api/user', fetchUserFromAPI),
...preload('/api/posts', fetchPostsFromAPI),
}
return (
{children}
)
}
```
--------------------------------
### Console output for failed then retried request
Source: https://swr.vercel.app/docs/advanced/performance
Shows the console output from the previous example when the first request fails and a retry succeeds. The four lines correspond to the four state changes and re-renders.
```js
// console.log(data, error, isLoading, isValidating)
undefined undefined true true // => start fetching
undefined Error false false // => end fetching, got an error
undefined Error true true // => start retrying
Data undefined false false // => end retrying, get the data
```
--------------------------------
### Global fetcher and refresh interval example
Source: https://swr.vercel.app/docs/global-configuration
Sets a global fetcher for JSON and a default refresh interval of 3000ms. Individual hooks can override the interval, as shown with the user hook.
```jsx
import useSWR, { SWRConfig } from 'swr'
function Dashboard () {
const { data: events } = useSWR('/api/events')
const { data: projects } = useSWR('/api/projects')
const { data: user } = useSWR('/api/user', { refreshInterval: 0 }) // override
// ...
}
function App () {
return (
fetch(resource, init).then(res => res.json())
}}
>
)
}
```
--------------------------------
### Preload data in a Next.js Server Component
Source: https://swr.vercel.app/docs/with-nextjs
Use preload to start a fetch request in a Server Component and pass the resulting CacheData object to SWRConfig. This requires SWR 2.5.0-beta.1 or later.
```tsx
import { preload, SWRConfig } from 'swr'
import { User } from './user'
const getUser = () => fetchUserFromDatabase()
export default function Page() {
const cacheData = preload('/api/user', getUser)
return (
)
}
```
--------------------------------
### Deduplication with useUser hook
Source: https://swr.vercel.app/docs/advanced/performance
Shows how reusing the same SWR key across multiple components results in only one network request due to deduplication. The example renders the current user's avatar five times, each using the same useUser hook, and only one request is made.
```jsx
function useUser () {
return useSWR('/api/user', fetcher)
}
function Avatar () {
const { data, error } = useUser()
if (error) return
if (!data) return
return
}
function App () {
return <>
>
}
```
--------------------------------
### Client Component with SWR
Source: https://swr.vercel.app/docs/with-nextjs
To use SWR client data fetching hooks in Next.js, mark the component with 'use client' directive or import SWR from a client component. This example demonstrates a simple component using useSWR in a client component.
```tsx
'use client'
import useSWR from 'swr'
export default function Page() {
const { data } = useSWR('/api/user', fetcher)
return
{data.name}
}
```
--------------------------------
### Conditional Fetching with useSWR
Source: https://swr.vercel.app/docs/conditional-fetching
Use null or a function as the key to conditionally fetch data. If the function throws or returns a falsy value, SWR will not start the request.
```js
// conditionally fetch
const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
// ...or return a falsy value
const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
// ...or throw an error when user.id is not defined
const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
```
--------------------------------
### Laggy Middleware with useRef and Usage Example
Source: https://swr.vercel.app/docs/middleware
Middleware that keeps the previous data when the key changes, exposing `isLagging` and `resetLaggy`. Use it by passing `use: [laggy]` to `useSWR`. The returned object includes `data`, `isLagging`, and `resetLaggy`.
```jsx
import { useRef, useEffect, useCallback } from 'react'
// This is a SWR middleware for keeping the data even if key changes.
function laggy(useSWRNext) {
return (key, fetcher, config) => {
// Use a ref to store previous returned data.
const laggyDataRef = useRef()
// Actual SWR hook.
const swr = useSWRNext(key, fetcher, config)
useEffect(() => {
// Update ref if data is not undefined.
if (swr.data !== undefined) {
laggyDataRef.current = swr.data
}
}, [swr.data])
// Expose a method to clear the laggy data, if any.
const resetLaggy = useCallback(() => {
laggyDataRef.current = undefined
}, [])
// Fallback to previous data if the current data is undefined.
const dataOrLaggyData = swr.data === undefined ? laggyDataRef.current : swr.data
// Is it showing previous data?
const isLagging = swr.data === undefined && laggyDataRef.current !== undefined
// Also add a `isLagging` field to SWR.
return Object.assign({}, swr, {
data: dataOrLaggyData,
isLagging,
resetLaggy,
})
}
}
// ... inside your component
useSWR(key, fetcher, { use: [laggy] })
```
```js
const { data, isLagging, resetLaggy } = useSWR(key, fetcher, { use: [laggy] })
```
--------------------------------
### Traditional data fetching with useEffect and prop drilling
Source: https://swr.vercel.app/docs/getting-started
Shows the traditional approach of fetching data in a top-level component and passing it down via props. This example does not handle error state and requires prop drilling through multiple levels.
```jsx
// page component
function Page ({ userId }) {
const [user, setUser] = useState(null)
// fetch data
useEffect(() => {
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(data => setUser(data))
}, [userId])
// global loading state
if (!user) return
return
}
// child components
function Navbar ({ user }) {
return
...
}
function Content ({ user }) {
return
Welcome back, {user.name}
}
function Avatar ({ user }) {
return
}
```
--------------------------------
### Basic subscribe function example
Source: https://swr.vercel.app/docs/subscription
A basic subscribe function that subscribes to a remote data source and returns an unsubscribe function. It uses the next callback to update state with received data.
```tsx
function subscribe(key, { next }) {
const sub = remote.subscribe(key, (err, data) => next(err, data))
return () => sub.close()
}
```
--------------------------------
### Fetch with GraphQL using graphql-request
Source: https://swr.vercel.app/docs/data-fetching
Uses graphql-request to send a GraphQL query. The fetcher takes a query string and posts it to '/api/graphql'. For passing variables, see the Multiple Arguments guide.
```javascript
import { request } from 'graphql-request'
const fetcher = query => request('/api/graphql', query)
function App () {
const { data, error } = useSWR(
`{
Movie(title: "Inception") {
releaseDate
actors {
name
}
}
}`,
fetcher
)
// ...
}
```
--------------------------------
### Update cache after mutation with useSWRMutation and populateCache
Source: https://swr.vercel.app/docs/mutation
Use the populateCache option with the useSWRMutation hook to update the cache with the mutation response. The example passes updateTodo and the same populateCache callback to useSWRMutation('/api/todos', updateTodo, { populateCache, revalidate: false }). The callback filters the list and returns it with the updated item. Setting revalidate to false avoids an extra fetch since the API already returns updated data.
```jsx
useSWRMutation('/api/todos', updateTodo, {
populateCache: (updatedTodo, todos) => {
// filter the list, and return it with the updated item
const filteredTodos = todos.filter(todo => todo.id !== '1')
return [...filteredTodos, updatedTodo]
},
// Since the API already gives us the updated information,
// we don't need to revalidate here.
revalidate: false
})
```
--------------------------------
### Typing SWR configuration
Source: https://swr.vercel.app/docs/typescript
Shows how to import and use SWRConfiguration to type configuration objects.
```typescript
import useSWR from 'swr'
import type { SWRConfiguration } from 'swr'
const config: SWRConfiguration = {
fallbackData: "fallback",
revalidateOnMount: false
// ...
}
const { data } = useSWR('/api/data', fetcher, config)
```
--------------------------------
### SWR 0.x Import Syntax
Source: https://swr.vercel.app/docs/pagination
Import syntax for users on SWR 0.x versions.
```text
import { useSWRInfinite } from 'swr'
```
--------------------------------
### Get scoped unload from useSWRConfig
Source: https://swr.vercel.app/docs/advanced/cache
Gets the scoped unload function from useSWRConfig for a custom cache provider. The button clears the cache without revalidation.
```tsx
import { useSWRConfig } from 'swr'
function ClearCacheButton() {
const { unload } = useSWRConfig()
return (
)
}
```
--------------------------------
### Using isLoading and isValidating for UX
Source: https://swr.vercel.app/docs/advanced/understanding
Demonstrates how to use isLoading to show a skeleton during initial load and isValidating to show a spinner during background revalidations.
```jsx
function Stock() {
const { data, isLoading, isValidating } = useSWR(STOCK_API, fetcher, {
refreshInterval: 3000
});
// If it's still loading the initial data, there is nothing to display.
// We return a skeleton here.
if (isLoading) return ;
// Otherwise, display the data and a spinner that indicates a background
// revalidation.
return (
<>
${data}
{isValidating ? : null}
>
);
}
```
--------------------------------
### Typing custom middleware
Source: https://swr.vercel.app/docs/typescript
Demonstrates how to use Middleware and SWRHook types to add types to custom SWR middleware.
```typescript
import useSWR, { Middleware, SWRHook } from 'swr'
const swrMiddleware: Middleware = (useSWRNext: SWRHook) => (key, fetcher, config) => {
// ...
return useSWRNext(key, fetcher, config)
}
```
--------------------------------
### Mutate string-based keys with a filter function
Source: https://swr.vercel.app/docs/mutation
Uses a filter function to revalidate all string keys starting with a specific API path prefix.
```jsx
import { mutate } from 'swr'
// Or from the hook if you customized the cache provider:
// { mutate } = useSWRConfig()
mutate(
key => typeof key === 'string' && key.startsWith('/api/item?id='),
undefined,
{ revalidate: true }
)
```
--------------------------------
### useSWRMutation basic implementation
Source: https://swr.vercel.app/docs/mutation
Demonstrates defining a fetcher that accepts an argument via the arg property and triggering it manually from a component.
```tsx
import useSWRMutation from 'swr/mutation'
// Fetcher implementation.
// The extra argument will be passed via the `arg` property of the 2nd parameter.
// In the example below, `arg` will be `'my_token'`
async function updateUser(url, { arg }: { arg: string }) {
await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${arg}`
}
})
}
function Profile() {
// A useSWR + mutate like API, but it will not start the request automatically.
const { trigger } = useSWRMutation('/api/user', updateUser, options)
return
}
```
--------------------------------
### Basic SWRConfig wrapper
Source: https://swr.vercel.app/docs/global-configuration
Wraps a component tree with SWRConfig to provide global options to all SWR hooks.
```jsx
```
--------------------------------
### Filter function key shape safety
Source: https://swr.vercel.app/docs/mutation
Examples of correctly matching specific key types versus an unsafe approach that may cause errors when keys have different shapes.
```jsx
// ✅ matching array key
mutate((key) => key[0].startsWith('/api'), data)
// ✅ matching string key
mutate((key) => typeof key === 'string' && key.startsWith('/api'), data)
// ❌ ERROR: mutate uncertain keys (array or string)
mutate((key: any) => /\/api/.test(key.toString()))
```
--------------------------------
### Implement basic pagination with useSWR
Source: https://swr.vercel.app/docs/pagination
A standard pagination UI implementation using useSWR and React state to track the current page index.
```jsx
function App () {
const [pageIndex, setPageIndex] = useState(0);
// The API URL includes the page index, which is a React state.
const { data } = useSWR(`/api/data?page=${pageIndex}`, fetcher);
// ... handle loading and error states
return
{data.map(item =>
{item.name}
)}
}
```
--------------------------------
### Pre-render with getStaticProps and SWRConfig
Source: https://swr.vercel.app/docs/with-nextjs
Uses getStaticProps to fetch data on the server and passes it to SWRConfig via the cacheData prop to hydrate the client-side SWR cache.
```jsx
export async function getStaticProps () {
// `getStaticProps` is executed on the server side.
const article = await getArticleFromAPI()
return {
props: {
cacheData: {
'/api/article': article
}
}
}
}
function Article() {
// `data` is available from the server-provided `cacheData`.
const { data } = useSWR('/api/article', fetcher)
return
{data.title}
}
export default function Page({ cacheData }) {
// SWR hooks inside the `SWRConfig` boundary will use those values.
return (
)
}
```
--------------------------------
### Cache Provider TypeScript Interface
Source: https://swr.vercel.app/docs/advanced/cache
Defines the Map-like interface that a cache provider must implement. It can be imported from 'swr'. The provider must support get, set, delete, and keys methods.
```typescript
interface Cache {
get(key: string): Data | undefined
set(key: string, value: Data): void
delete(key: string): void
keys(): IterableIterator
}
```
--------------------------------
### Create Cache Provider with SWRConfig
Source: https://swr.vercel.app/docs/advanced/cache
Shows how to create a cache provider by passing a function that returns a Map to the 'provider' option of SWRConfig. All SWR hooks inside the boundary will use this provider. Note that the provider is re-created when the component re-mounts, so it should be placed higher in the tree or outside render.
```jsx
import useSWR, { SWRConfig } from 'swr'
function App() {
return (
new Map() }}>
)
}
```
--------------------------------
### useSWRInfinite type specification
Source: https://swr.vercel.app/docs/typescript
Shows how to use SWRInfiniteKeyLoader to define types for useSWRInfinite.
```typescript
import { SWRInfiniteKeyLoader } from 'swr/infinite'
const getKey: SWRInfiniteKeyLoader = (index, previousPageData) => {
// ...
}
const { data } = useSWRInfinite(getKey, fetcher)
```
--------------------------------
### Equivalent fetcher argument forms
Source: https://swr.vercel.app/docs/arguments
Shows three equivalent ways to pass the key to the fetcher: an inline arrow function, a function that receives the key as a parameter, or the fetcher directly.
```javascript
useSWR('/api/user', () => fetcher('/api/user'))
useSWR('/api/user', url => fetcher(url))
useSWR('/api/user', fetcher)
```
--------------------------------
### useSWRInfinite(getKey, fetcher?, options?)
Source: https://swr.vercel.app/docs/pagination
A React Hook that triggers multiple requests for paginated data. It accepts a getKey function, an optional fetcher, and options, and returns data, error, loading states, mutate, size, and setSize.
```APIDOC
## useSWRInfinite(getKey, fetcher?, options?)
### Description
A React Hook that enables infinite loading by fetching multiple pages of data. It accepts a function that returns the request key for each page, a fetcher function, and options. Returns an array of page data and utilities to control pagination.
### Method
Hook
### Parameters
#### getKey
- **getKey** (function) - Required - A function that accepts the page index and previous page data, returns the key of a page. Return null to stop fetching that page.
#### fetcher
- **fetcher** (function) - Optional - Same as useSWR's fetcher function.
#### options
- **options** (object) - Optional - Accepts all options from useSWR, plus:
- **initialSize** (number) - Optional - Number of pages to load initially. Default is 1. Cannot change during lifecycle.
- **revalidateAll** (boolean) - Optional - Always try to revalidate all pages. Default is false.
- **revalidateFirstPage** (boolean) - Optional - Always try to revalidate the first page. Default is true.
- **persistSize** (boolean) - Optional - Don't reset page size to 1 (or initialSize) when first page's key changes. Default is false.
- **parallel** (boolean) - Optional - Fetch multiple pages in parallel. Default is false.
### Return Values
- **data** (array) - An array of fetch response values for each page.
- **error** (any) - Same as useSWR's error.
- **isLoading** (boolean) - Same as useSWR's isLoading.
- **isValidating** (boolean) - Same as useSWR's isValidating.
- **mutate** (function) - Same as useSWR's bound mutate but manipulates the data array.
- **size** (number) - The number of pages that will be fetched and returned.
- **setSize** (function) - Set the number of pages that need to be fetched.
### Example: Index Based Paginated API
```jsx
const getKey = (pageIndex, previousPageData) => {
if (previousPageData && !previousPageData.length) return null
return `/users?page=${pageIndex}&limit=10`
}
function App () {
const { data, size, setSize } = useSWRInfinite(getKey, fetcher)
if (!data) return 'loading'
let totalUsers = 0
for (let i = 0; i < data.length; i++) {
totalUsers += data[i].length
}
return
}
```
### Example: Cursor or Offset Based Paginated API
```jsx
const getKey = (pageIndex, previousPageData) => {
if (previousPageData && !previousPageData.data) return null
if (pageIndex === 0) return `/users?limit=10`
return `/users?cursor=${previousPageData.nextCursor}&limit=10`
}
```
```
--------------------------------
### Pre-render with complex keys using unstable_serialize
Source: https://swr.vercel.app/docs/with-nextjs
Demonstrates how to use unstable_serialize to manually serialize array-style keys when pre-rendering data with SWRConfig.
```jsx
import useSWR, { unstable_serialize } from 'swr'
export async function getStaticProps () {
const article = await getArticleFromAPI(1)
return {
props: {
cacheData: {
// unstable_serialize() array style key
[unstable_serialize(['api', 'article', 1])]: article,
}
}
}
}
function Article() {
// using an array style key.
const { data } = useSWR(['api', 'article', 1], fetcher)
return
{data.title}
}
function Page({ cacheData }) {
return (
)
}
```
--------------------------------
### Clear all cache data with mutate
Source: https://swr.vercel.app/docs/advanced/cache
Modify the cache data using the mutate function from useSWRConfig. This example clears all cache data by updating every key to undefined and disabling revalidation. Do not write to the cache directly, as it might cause undefined behavior.
```jsx
const { mutate } = useSWRConfig()
mutate(
key => true, // which cache keys are updated
undefined, // update cache data to `undefined`
{ revalidate: false } // do not revalidate
)
```
--------------------------------
### Preload next page with SWR cache
Source: https://swr.vercel.app/docs/pagination
Improves UX by rendering the next page in a hidden div, allowing SWR to pre-fetch the data.
```jsx
function App () {
const [pageIndex, setPageIndex] = useState(0);
return
}
```
--------------------------------
### Equivalent middleware configuration
Source: https://swr.vercel.app/docs/middleware
Nested middleware configurations are equivalent to a single array of middleware.
```js
useSWR(key, fetcher, { use: [a, b, c] })
```
--------------------------------
### Reset cache between test cases with Jest
Source: https://swr.vercel.app/docs/advanced/cache
Reset the SWR cache between test cases by wrapping the application with an empty cache provider. This example uses Jest and renders the app inside a with a provider that returns a new Map, giving each test case a fresh cache.
```jsx
describe('test suite', async () => {
it('test case', async () => {
render(
new Map() }}>
)
})
})
```
--------------------------------
### Multiple arguments with array key
Source: https://swr.vercel.app/docs/arguments
Correct way to pass multiple arguments: use an array as the key. The fetcher receives the array as is, and the cache key includes both the URL and the token.
```javascript
const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
```
--------------------------------
### Update cache after mutation with mutate and populateCache
Source: https://swr.vercel.app/docs/mutation
Use the populateCache option with mutate to update the cache for useSWR with the response of the mutation. The example defines an updateTodo function that PATCHes /api/todos/1, then calls mutate('/api/todos', updateTodo, { populateCache, revalidate: false }). The populateCache callback filters the list and returns it with the updated item. Setting revalidate to false avoids an extra fetch since the API already returns updated data.
```jsx
const updateTodo = () => fetch('/api/todos/1', {
method: 'PATCH',
body: JSON.stringify({ completed: true })
})
mutate('/api/todos', updateTodo, {
populateCache: (updatedTodo, todos) => {
// filter the list, and return it with the updated item
const filteredTodos = todos.filter(todo => todo.id !== '1')
return [...filteredTodos, updatedTodo]
},
// Since the API already gives us the updated information,
// we don't need to revalidate here.
revalidate: false
})
```
--------------------------------
### Configure middleware in SWRConfig or useSWR
Source: https://swr.vercel.app/docs/middleware
Pass an array of middleware functions to the use option within SWRConfig or directly in the useSWR hook.
```jsx
// or...
useSWR(key, fetcher, { use: [myMiddleware] })
```
--------------------------------
### Pre-fill Data with fallbackData
Source: https://swr.vercel.app/docs/prefetching
Use the fallbackData option to provide initial data to the SWR cache before the fetcher completes.
```jsx
useSWR('/api/data', fetcher, { fallbackData: prefetchedData })
```
--------------------------------
### useSWR(key, fetcher, options)
Source: https://swr.vercel.app/docs/api
The main hook for data fetching in SWR. It accepts a unique key, an optional fetcher function, and an options object, returning data, error, loading states, and a mutate function.
```APIDOC
## useSWR(key, fetcher, options)
### Description
This is the primary hook for data fetching in SWR. It takes a unique key, an optional fetcher function, and an options object, and returns the data, error, loading states, and a mutate function.
### Parameters
- **key** (string | function | array | null) - Required - A unique key for the request.
- **fetcher** (function) - Optional - A Promise-returning function to fetch data.
- **options** (object) - Optional - An object of options for this SWR hook.
### Return Values
- **data** - Data for the given key resolved by fetcher (or undefined if not loaded).
- **error** - Error thrown by fetcher (or undefined).
- **isLoading** - If there's an ongoing request and no loaded data.
- **isValidating** - If there's a request or revalidation loading.
- **mutate(data?, options?)** - Function to mutate the cached data.
### Options
- **suspense** (boolean) - Optional - Enable React Suspense mode. Default: false.
- **fetcher(args)** (function) - Optional - The fetcher function.
- **revalidateIfStale** (boolean) - Optional - Automatically revalidate even if there is stale data. Default: true.
- **revalidateOnMount** (boolean) - Optional - Enable or disable automatic revalidation when component is mounted.
- **revalidateOnFocus** (boolean) - Optional - Automatically revalidate when window gets focused. Default: true.
- **revalidateOnReconnect** (boolean) - Optional - Automatically revalidate when the browser regains a network connection. Default: true.
- **refreshInterval** (number | function) - Optional - Polling interval in milliseconds. Disabled by default (0). If a function, receives latest data and returns interval.
- **refreshWhenHidden** (boolean) - Optional - Polling when the window is invisible. Default: false.
- **refreshWhenOffline** (boolean) - Optional - Polling when the browser is offline. Default: false.
- **shouldRetryOnError** (boolean) - Optional - Retry when fetcher has an error. Default: true.
- **dedupingInterval** (number) - Optional - Dedupe requests with the same key in this time span in milliseconds. Default: 2000.
- **focusThrottleInterval** (number) - Optional - Only revalidate once during a time span in milliseconds. Default: 5000.
- **loadingTimeout** (number) - Optional - Timeout to trigger the onLoadingSlow event in milliseconds. Default: 3000.
- **errorRetryInterval** (number) - Optional - Error retry interval in milliseconds. Default: 5000.
- **errorRetryCount** (number) - Optional - Max error retry count.
- **fallback** (object) - Optional - A key-value object of multiple fallback data.
- **fallbackData** (any) - Optional - Initial data to be returned (per-hook).
- **strictServerPrefetchWarning** (boolean) - Optional - Show a warning message when a key has no pre-filled data provided. Default: false.
- **keepPreviousData** (boolean) - Optional - Return the previous key's data until the new data has been loaded. Default: false.
- **onLoadingSlow(key, config)** (function) - Optional - Callback when a request takes too long to load.
- **onSuccess(data, key, config)** (function) - Optional - Callback when a request finishes successfully.
- **onError(err, key, config)** (function) - Optional - Callback when a request returns an error.
- **onErrorRetry(err, key, config, revalidate, revalidateOps)** (function) - Optional - Handler for error retry.
- **onDiscarded(key)** (function) - Optional - Callback when a request is ignored due to race conditions.
- **compare(a, b)** (function) - Optional - Comparison function used to detect when returned data has changed.
- **isPaused()** (function) - Optional - Function to detect whether to pause revalidations. Returns false by default.
- **use** (array) - Optional - Array of middleware functions.
### Example
```js
const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options)
```
```
--------------------------------
### Enable Parallel Fetching in useSWRInfinite
Source: https://swr.vercel.app/docs/pagination
Set the parallel option to true to fetch pages independently instead of sequentially. Note that previousPageData will be null when this mode is enabled.
```jsx
// parallel = false (default)
// page1 ===> page2 ===> page3 ===> done
//
// parallel = true
// page1 ==> done
// page2 =====> done
// page3 ===> done
//
// previousPageData is always `null`
const getKey = (pageIndex, previousPageData) => {
return `/users?page=${pageIndex}&limit=10`
}
function App () {
const { data } = useSWRInfinite(getKey, fetcher, { parallel: true })
}
```
--------------------------------
### useSWRSubscription with inline type
Source: https://swr.vercel.app/docs/typescript
Demonstrates manually specifying the type of next using SWRSubscriptionOptions within useSWRSubscription.
```tsx
import useSWRSubscription from 'swr/subscription'
import type { SWRSubscriptionOptions } from 'swr/subscription'
const { data, error } = useSWRSubscription('key',
(key, { next }: SWRSubscriptionOptions) => {
//^ key will be inferred as `string`
//....
})
return {
data,
//^ data will be inferred as `number | undefined`
error
//^ error will be inferred as `Error | undefined`
}
}
```
--------------------------------
### Fetch with Axios
Source: https://swr.vercel.app/docs/data-fetching
Uses Axios to create a fetcher that returns the response data. The fetcher is passed to useSWR with the '/api/data' key.
```javascript
import axios from 'axios'
const fetcher = url => axios.get(url).then(res => res.data)
function App () {
const { data, error } = useSWR('/api/data', fetcher)
// ...
}
```
--------------------------------
### Customize focus and reconnect events
Source: https://swr.vercel.app/docs/advanced/react-native
Configure SWR for React Native by customizing isOnline, isVisible, initFocus, and initReconnect. Requires a custom cache provider (e.g., an empty Map) when using initFocus and initReconnect.
```jsx
new Map(),
isOnline() {
/* Customize the network state detector */
return true
},
isVisible() {
/* Customize the visibility state detector */
return true
},
initFocus(callback) {
/* Register the listener with your state provider */
},
initReconnect(callback) {
/* Register the listener with your state provider */
}
}}
>
```
--------------------------------
### Global Mutate via Import
Source: https://swr.vercel.app/docs/mutation
You can also import the mutate function directly from the swr package.
```javascript
import { mutate } from "swr"
function App() {
mutate(key, data, options)
}
```
--------------------------------
### Array key with fetchWithToken and conditional fetchWithUser
Source: https://swr.vercel.app/docs/arguments
Shows passing an array key to a fetcher that expects multiple arguments, and then using the result as a dependency for another useSWR call with a conditional key.
```javascript
const { data: user } = useSWR(['/api/user', token], fetchWithToken)
// ...and then pass it as an argument to another useSWR hook
const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
```
--------------------------------
### Basic useSWR API with fetcher
Source: https://swr.vercel.app/docs/data-fetching
The fundamental SWR API. The fetcher is an async function that accepts the key and returns data; if it throws, the error is caught. The fetcher can be omitted if provided globally.
```javascript
const { data, error } = useSWR(key, fetcher)
```
--------------------------------
### LocalStorage based persistent cache provider
Source: https://swr.vercel.app/docs/advanced/cache
Create a localStorage-based persistent cache provider. The provider restores data from localStorage into a Map on initialization and writes it back on the beforeunload event. Use it as the provider in to persist the cache across page reloads. As an improvement, you can use the memory cache as a buffer and write to localStorage periodically, or implement a similar layered cache with IndexedDB or WebSQL.
```jsx
function localStorageProvider() {
// When initializing, we restore the data from `localStorage` into a map.
const map = new Map(JSON.parse(localStorage.getItem('app-cache') || '[]'))
// Before unloading the app, we write back all the data into `localStorage`.
window.addEventListener('beforeunload', () => {
const appCache = JSON.stringify(Array.from(map.entries()))
localStorage.setItem('app-cache', appCache)
})
// We still use the map for write & read for performance.
return map
}
```
```jsx
```
--------------------------------
### Nested SWRConfig with functional value
Source: https://swr.vercel.app/docs/global-configuration
Shows how a functional configuration receives the parent config and returns a new one. The resulting config is shown in the comment.
```jsx
import { SWRConfig, useSWRConfig } from 'swr'
function App() {
return (
({
dedupingInterval: parent.dedupingInterval * 5,
fallback: { a: 2, c: 2 },
})}
>
)
}
function Page() {
const config = useSWRConfig()
// {
// dedupingInterval: 500,
// fallback: { a: 2, c: 2 },
// }
}
```
--------------------------------
### Import SWR APIs in Server Components
Source: https://swr.vercel.app/docs/with-nextjs
In Next.js App Router, all components are RSC by default. The SWRConfig component and key serialization functions are available in server components for use in RSC.
```tsx
import { unstable_serialize } from 'swr' // ✅ Available in server components
import { unstable_serialize as infinite_unstable_serialize } from 'swr/infinite' // ✅ Available in server components
import { SWRConfig } from 'swr' // ✅ Available in server components
import { preload } from 'swr' // ✅ Available in server components
```
--------------------------------
### useSWRSubscription with SWRSubscription type
Source: https://swr.vercel.app/docs/typescript
Shows how to declare a subscription function using the SWRSubscription generic type.
```tsx
import useSWRSubscription from 'swr/subscription'
import type { SWRSubscription } from 'swr/subscription'
/**
* The first generic is Key
* The second generic is Data
* The Third generic is Error
*/
const sub: SWRSubscription = (key, { next }) => {
//......
}
const { data, error } = useSWRSubscription('key', sub)
```
--------------------------------
### Using keepPreviousData for Search UI
Source: https://swr.vercel.app/docs/advanced/understanding
Shows how to maintain previous data while fetching new results during user input by enabling the keepPreviousData option.
```jsx
function Search() {
const [search, setSearch] = React.useState('');
const { data, isLoading } = useSWR(`/search?q=${search}`, fetcher, {
keepPreviousData: true
});
return (
);
}
```
--------------------------------
### Fetch with unfetch polyfill
Source: https://swr.vercel.app/docs/data-fetching
Uses the unfetch polyfill to create a fetcher that returns JSON. For Next.js, the polyfill is not needed as it has built-in fetch support.
```javascript
import fetch from 'unfetch'
const fetcher = url => fetch(url).then(r => r.json())
function App () {
const { data, error } = useSWR('/api/data', fetcher)
// ...
}
```
--------------------------------
### useSWRMutation(key, fetcher, options)
Source: https://swr.vercel.app/docs/mutation
The useSWRMutation hook provides a way to trigger mutations and manage the mutation state. It returns a trigger function that can be called to perform the mutation.
```APIDOC
## useSWRMutation(key, fetcher, options)
### Description
Provides a mutation function that can be used to trigger remote data mutations and update the cache. The returned mutate function is bound to the provided key.
### Method
N/A (JavaScript API)
### Endpoint
N/A
### Parameters
- **key** (any) - Required - The key of the SWR hook to mutate.
- **fetcher** (function) - Required - The async function to perform the remote mutation.
- **options** (object) - Optional - Configuration options for the mutation.
### Return Values
Returns an object containing the mutation function and related state (e.g., `data`, `error`, `isMutating`).
### Example
```js
import useSWRMutation from 'swr'
function Profile () {
const { trigger } = useSWRMutation('/api/user', updateUser)
return
}
```
```
--------------------------------
### Share data across components
Source: https://swr.vercel.app
Demonstrates how multiple components can call the same custom hook to share cached data without prop drilling.
```javascript
function Content({ userId }) {
const { user, isLoading } = useUser(userId)
if (isLoading) return
return
Welcome back, {user.name}
}
function Avatar({ userId }) {
const { user, isLoading } = useUser(userId)
if (isLoading) return
return
}
```
--------------------------------
### Middleware execution order
Source: https://swr.vercel.app/docs/middleware
The execution flow follows a nested pattern where each middleware wraps the next.
```plaintext
enter a
enter b
enter c
useSWR()
exit c
exit b
exit a
```