### Install Dependencies and Start Dev Server Source: https://github.com/vercel/swr-site/blob/main/README.md Use these commands to install project dependencies with pnpm and start the local development server. Visit localhost:3000 to preview changes. ```bash pnpm install pnpm dev ``` -------------------------------- ### Basic useSWRMutation Setup Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.es.mdx Demonstrates the basic setup for useSWRMutation, including defining a fetcher function and triggering the mutation. The fetcher receives the URL and an argument object. ```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 } ``` -------------------------------- ### Install SWR Source: https://github.com/vercel/swr-site/blob/main/content/docs/getting-started.mdx Run this command in your React project directory to install SWR. ```bash npm i swr ``` -------------------------------- ### Example 1: Index Based Paginated API Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Demonstrates how to use useSWRInfinite with an index-based pagination API. The `getKey` function generates request keys based on the page index. ```APIDOC ## Example 1: Index Based Paginated API ### Description This example shows how to fetch data from an index-based paginated API using `useSWRInfinite`. ### Request Example (API) ```plaintext GET /users?page=0&limit=10 [ { name: 'Alice', ... }, { name: 'Bob', ... }, { name: 'Cathy', ... }, ... ] ``` ### Code Example (React) ```jsx import useSWRInfinite from 'swr/infinite' // 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}
) })}
} ``` ### Notes - The `getKey` function is crucial for `useSWRInfinite` and determines the request key for each page based on the page index and previous page data. - The `data` returned by `useSWRInfinite` is an array of arrays, where each inner array represents the data for a single page. ``` -------------------------------- ### Integrate SWR with Next.js App and Pages Router Source: https://context7.com/vercel/swr-site/llms.txt Examples demonstrating server-side prefetching in App Router layouts, client-side consumption, and Pages Router static generation with fallback data. ```jsx // app/layout.tsx - Server Component with prefetching import { SWRConfig } from 'swr' async function fetchUser() { const res = await fetch('https://api.example.com/user') return res.json() } export default async function RootLayout({ children }) { // Initiate fetching on server const userPromise = fetchUser() return ( {children} ) } // app/page.tsx - Client Component 'use client' import useSWR from 'swr' const fetcher = url => fetch(url).then(res => res.json()) export default function Page() { // Data is pre-filled from server, then kept fresh on client const { data: user } = useSWR('/api/user', fetcher) return

Hello, {user?.name}

} // pages/posts.js - Pages Router with getStaticProps import useSWR, { SWRConfig, unstable_serialize } from 'swr' export async function getStaticProps() { const posts = await fetchPosts() return { props: { fallback: { '/api/posts': posts, // For array keys, use unstable_serialize [unstable_serialize(['posts', 'featured'])]: await fetchFeaturedPosts() } }, revalidate: 60 } } export default function PostsPage({ fallback }) { return ( ) } function PostList() { // Pre-rendered data available immediately const { data } = useSWR('/api/posts', fetcher) return data?.map(post =>
{post.title}
) } ``` -------------------------------- ### Example 2: Cursor or Offset Based Paginated API Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Illustrates using useSWRInfinite with a cursor-based pagination API. The `getKey` function dynamically includes the cursor from the previous page's response. ```APIDOC ## Example 2: Cursor or Offset Based Paginated API ### Description This example demonstrates how to use `useSWRInfinite` with a cursor-based or offset-based paginated API, where the next page's request depends on a cursor provided in the previous response. ### Request Example (API) ```plaintext GET /users?cursor=123&limit=10 { data: [ { name: 'Alice' }, { name: 'Bob' }, { name: 'Cathy' }, ... ], nextCursor: 456 } ``` ### Code Example (React) ```jsx import useSWRInfinite from 'swr/infinite' 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` } // ... rest of the component using useSWRInfinite with this getKey function ``` ### Notes - The `getKey` function is adapted to use the `nextCursor` from the `previousPageData` to construct the URL for the subsequent page. - This approach allows `useSWRInfinite` to handle various pagination strategies effectively. ``` -------------------------------- ### Configure SWR with LocalStorage Cache Provider Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/cache.es.mdx Example of integrating the localStorageProvider into SWRConfig to enable persistent caching across page reloads or application restarts. ```jsx ``` -------------------------------- ### Data Fetching with SWR useUser Hook Source: https://github.com/vercel/swr-site/blob/main/content/docs/getting-started.mdx This refactored example uses a `useUser` hook with SWR to fetch data directly within the components that need it. This simplifies prop drilling and improves maintainability. ```jsx // page component function Page ({ userId }) { return
} // child components function Navbar ({ userId }) { return
...
} 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 {user.name} } ``` -------------------------------- ### Subscribe Function Example Source: https://github.com/vercel/swr-site/blob/main/content/docs/subscription.mdx An example of a subscribe function that uses a remote service to subscribe to data and returns a cleanup function. ```typescript function subscribe(key, { next }) { const sub = remote.subscribe(key, (err, data) => next(err, data)) return () => sub.close() } ``` -------------------------------- ### Cursor Based Paginated API Key Generation Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Example of a `getKey` function for a cursor-based paginated API. It uses the `nextCursor` from the previous page's data to fetch the subsequent page. ```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` } ``` -------------------------------- ### Index Based Paginated API Key Generation Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Example of a `getKey` function for an index-based paginated API. It constructs the request URL based on the page index and stops when the previous page returns no data. ```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 } ``` -------------------------------- ### Use SWR Hooks in Client Components Source: https://github.com/vercel/swr-site/blob/main/content/docs/with-nextjs.es.mdx To use SWR's client-side data fetching hooks, mark your component with the 'use client' directive or import SWR within a client component. This example shows basic usage with a fetcher function. ```tsx 'use client' import useSWR from 'swr' export default function Page() { const { data } = useSWR('/api/user', fetcher) return

{data.name}

} ``` -------------------------------- ### Mutate Multiple Cache Items by Key Prefix Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.mdx Use a filter function with the global `mutate` API to revalidate specific cache keys. This example revalidates all keys starting with '/api/item?id='. ```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 } ) ``` -------------------------------- ### Mutate Multiple Keys with Filter Function Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v2.mdx Demonstrates how to use the global `mutate` function with a filter to revalidate or clear specific cached keys. This example clears all keys starting with '/api/item?id='. ```jsx import { mutate } from 'swr' // Or from the hook if you have customized your cache provider: // { mutate } = useSWRConfig() // Mutate single resource mutate(key) // Mutate multiple resources and clear the cache (set to undefined) mutate( key => typeof key === 'string' && key.startsWith('/api/item?id=') , undefined, { revalidate: false } ) ``` -------------------------------- ### Import and Basic Usage of useSWRInfinite Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Demonstrates how to import and use the useSWRInfinite hook. It returns data, error, loading states, and functions to manage page size. ```jsx import useSWRInfinite from 'swr/infinite' // ... const { data, error, isLoading, isValidating, mutate, size, setSize } = useSWRInfinite( getKey, fetcher?, options? ) ``` -------------------------------- ### Import SWR Hooks Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Import the main SWR hook and the infinite hook. If `useSWRInfinite` is not used, it won't be included in the bundle. ```javascript import useSWR from 'swr' import useSWRInfinite from 'swr/infinite' ``` -------------------------------- ### Pass arguments to fetcher Source: https://github.com/vercel/swr-site/blob/main/content/docs/arguments.mdx Demonstrates equivalent ways to pass the key to the fetcher function. ```js useSWR('/api/user', () => fetcher('/api/user')) useSWR('/api/user', url => fetcher(url)) useSWR('/api/user', fetcher) ``` -------------------------------- ### Subscribe Function with Updater Source: https://github.com/vercel/swr-site/blob/main/content/docs/subscription.mdx An example of a subscribe function where the `next` callback receives an updater function to modify the previous data. ```typescript function subscribe(key, { next }) { const sub = remote.subscribe(key, (err, data) => next(err, prev => prev.concat(data))) return () => sub.close() } ``` -------------------------------- ### Subscribe to WebSocket Data Source: https://github.com/vercel/swr-site/blob/main/content/docs/subscription.mdx Example of using `useSWRSubscription` to subscribe to messages from a WebSocket server. Handles loading, error, and data states. ```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}!
} ``` -------------------------------- ### Define Cache Provider Interface Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/cache.es.mdx TypeScript interface defining the expected methods for a SWR cache provider: get, set, delete, and keys. ```typescript interface Cache { get(key: string): Data | undefined set(key: string, value: Data): void delete(key: string): void keys(): IterableIterator } ``` -------------------------------- ### Subscribe to Firestore Views Source: https://github.com/vercel/swr-site/blob/main/content/docs/subscription.mdx Example of using `useSWRSubscription` to subscribe to real-time view counts from a Firestore database. Ensure you have the latest SWR version (>= 2.1.0). ```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! } ``` -------------------------------- ### Import useSWRInfinite for SWR 0.x Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Shows the correct import path for useSWRInfinite when using older versions of SWR (0.x). ```jsx import { useSWRInfinite } from 'swr' ``` -------------------------------- ### Pass objects as keys Source: https://github.com/vercel/swr-site/blob/main/content/docs/arguments.mdx Demonstrates passing objects as keys and chaining SWR hooks using object-based keys. ```js 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) ``` ```js const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher) ``` -------------------------------- ### Implement Pagination with useSWRInfinite Source: https://context7.com/vercel/swr-site/llms.txt Uses useSWRInfinite to manage multiple pages of data. The getKey function handles both offset-based and cursor-based pagination logic. ```jsx import useSWRInfinite from 'swr/infinite' const fetcher = url => fetch(url).then(res => res.json()) // getKey function determines the key for each page const getKey = (pageIndex, previousPageData) => { // Reached the end (no more data) if (previousPageData && !previousPageData.length) return null // First page, no previousPageData if (pageIndex === 0) return '/api/posts?limit=10' // Return key for next page return `/api/posts?limit=10&offset=${pageIndex * 10}` } // For cursor-based pagination const getCursorKey = (pageIndex, previousPageData) => { if (previousPageData && !previousPageData.nextCursor) return null if (pageIndex === 0) return '/api/posts?limit=10' return `/api/posts?limit=10&cursor=${previousPageData.nextCursor}` } function PostList() { const { data, error, isLoading, isValidating, mutate, size, setSize } = useSWRInfinite(getKey, fetcher, { initialSize: 1, revalidateAll: false, revalidateFirstPage: true, persistSize: false, parallel: false // Set true to fetch pages in parallel }) // Flatten all pages into single array const posts = data ? data.flat() : [] const isEmpty = data?.[0]?.length === 0 const isReachingEnd = isEmpty || (data && data[data.length - 1]?.length < 10) const isLoadingMore = isLoading || (size > 0 && data && typeof data[size - 1] === 'undefined') if (error) return
Error loading posts
if (isLoading) return
Loading...
return (

Showing {posts.length} posts

{posts.map(post => (

{post.title}

{post.excerpt}

))}
) } ``` -------------------------------- ### Mutate Multiple Cache Items by Array Key Prefix Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.mdx This example demonstrates mutating multiple cache entries where keys are arrays, specifically targeting keys where the first element is 'item'. ```jsx useSWR(['item', 123], ...) useSWR(['item', 124], ...) useSWR(['item', 125], ...) mutate( key => Array.isArray(key) && key[0] === 'item', undefined, { revalidate: false } ) ``` -------------------------------- ### Implement basic pagination with useSWR Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Use a React state variable to track the current page index and update the SWR key dynamically. ```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}
)}
} ``` -------------------------------- ### Update useSWRInfinite Imports Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Update import paths for the useSWRInfinite hook and its associated types to the swr/infinite entry point. ```diff - import { useSWRInfinite } from 'swr' + import useSWRInfinite from 'swr/infinite' ``` ```diff - import { SWRInfiniteConfiguration, SWRInfiniteResponse } from 'swr' + import { SWRInfiniteConfiguration, SWRInfiniteResponse } from 'swr/infinite' ``` -------------------------------- ### Configure Default Fetcher with SWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.mdx SWR no longer provides a default fetcher. Configure a global fetcher using the `` component or provide it directly to `useSWR`. ```jsx fetch(url).then(res => res.json()) }}> ``` ```javascript useSWR(key, (url) => fetch(url).then(res => res.json())) ``` -------------------------------- ### Configure Default Fetcher Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Provide a custom fetcher globally via SWRConfig or locally within the useSWR hook, as there is no longer a default fetcher. ```jsx fetch(url).then(res => res.json()) }}> // ... or useSWR(key, (url) => fetch(url).then(res => res.json())) ``` -------------------------------- ### Clear All SWR Cache Data Using Mutate Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/cache.es.mdx Use the `mutate` function from `useSWRConfig` to clear all cache data. This example targets all cache keys and sets their data to undefined without triggering a revalidation. ```jsx const { mutate } = useSWRConfig() mutate( key => true, // which cache keys are updated undefined, // update cache data to `undefined` { revalidate: false } // do not revalidate ) ``` -------------------------------- ### Handle multiple arguments Source: https://github.com/vercel/swr-site/blob/main/content/docs/arguments.mdx Shows the incorrect approach using a closure and the correct approach using an array as the key to ensure cache consistency. ```js useSWR('/api/user', url => fetchWithToken(url, token)) ``` ```js const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token)) ``` -------------------------------- ### Conditionally fetch data with SWR Source: https://github.com/vercel/swr-site/blob/main/content/docs/conditional-fetching.mdx Use null or a function returning a falsy value as the key to prevent SWR from starting a request. Throwing an error within the key function also halts 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) ``` -------------------------------- ### Pre-rendering with getStaticProps Source: https://github.com/vercel/swr-site/blob/main/content/docs/with-nextjs.es.mdx Uses SWRConfig to inject pre-fetched data into SWR hooks during static generation. ```jsx export async function getStaticProps () { // `getStaticProps` is executed on the server side. const article = await getArticleFromAPI() return { props: { fallback: { '/api/article': article } } } } function Article() { // `data` will always be available as it's in `fallback`. const { data } = useSWR('/api/article', fetcher) return

{data.title}

} export default function Page({ fallback }) { // SWR hooks inside the `SWRConfig` boundary will use those values. return (
) } ``` -------------------------------- ### Enable Parallel Fetching in useSWRInfinite Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx Set the `parallel` option to `true` to fetch pages independently and in parallel. This can significantly speed up loading when pages are not interdependent. Note that `previousPageData` will be `null` when `parallel` 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 }) } ``` -------------------------------- ### App Component with useSWRInfinite for Index Based Pagination Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx A React component demonstrating how to use `useSWRInfinite` with an index-based API. It fetches user data, calculates the total number of users, and provides a 'Load More' button. ```jsx 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}
) })}
} ``` -------------------------------- ### Configure SWR with a Custom Map Cache Provider Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/cache.es.mdx Example of configuring SWR to use a JavaScript Map instance as its cache provider within an SWRConfig boundary. This ensures all SWR hooks within the component tree use this specific Map for caching. ```jsx import useSWR, { SWRConfig } from 'swr' function App() { return ( new Map() }}> ) } ``` -------------------------------- ### Use useSWRMutation for Declarative Data Mutations Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v2.ko.mdx Use `useSWRMutation` to declaratively set up remote data mutations. It returns a `trigger` function to initiate the mutation manually, unlike `useSWR` which starts requests on render. The `isMutating` state indicates the mutation's progress. ```jsx import useSWRMutation from 'swr/mutation' async function sendRequest(url, { arg }) { return fetch(url, { method: 'POST', body: JSON.stringify(arg) }) } function App() { const { trigger, isMutating } = useSWRMutation('/api/user', sendRequest) return ( ) } ``` -------------------------------- ### Configure Middleware with SWRConfig or useSWR Source: https://github.com/vercel/swr-site/blob/main/content/docs/middleware.es.mdx Pass an array of middleware functions to the 'use' option in SWRConfig for global application or directly in useSWR for specific hooks. ```jsx ``` ```jsx useSWR(key, fetcher, { use: [myMiddleware] }) ``` -------------------------------- ### useSWRInfinite API Source: https://github.com/vercel/swr-site/blob/main/content/docs/pagination.mdx The useSWRInfinite hook provides functionality for fetching multiple pages of data. It accepts a getKey function, a fetcher function, and options, returning data, error, loading states, and pagination controls. ```APIDOC ## useSWRInfinite API ### Description Provides the ability to trigger a number of requests with one hook for infinite loading scenarios. ### Parameters - `getKey` (function): A function that accepts the index and the previous page data, and returns the key for a page. If `null` is returned, the request for that page will not start. - `fetcher` (function): Same as `useSWR`'s fetcher function. - `options` (object): Accepts all options supported by `useSWR`, with 4 extra options: - `initialSize` (number): Defaults to 1. The number of pages to load initially. This option is not allowed to change in the lifecycle. - `revalidateAll` (boolean): Defaults to `false`. If `true`, always try to revalidate all pages. - `revalidateFirstPage` (boolean): Defaults to `true`. If `true`, always try to revalidate the first page. - `persistSize` (boolean): Defaults to `false`. If `true`, the page size is not reset to 1 (or `initialSize` if set) when the first page's key changes. - `parallel` (boolean): Defaults to `false`. If `true`, fetches multiple pages in parallel. ### Return Values - `data` (array): An array of fetch response values for each page. The structure is `[[page1_data], [page2_data], ...]`. - `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 function but manipulates the data array. - `size` (number): The number of pages that will be fetched and returned. - `setSize` (function): A function to set the number of pages that need to be fetched. ``` -------------------------------- ### HTML Link Preload for Top-Level Data Source: https://github.com/vercel/swr-site/blob/main/content/docs/prefetching.mdx Use `rel="preload"` in your HTML `` to prefetch data when the HTML loads, even before JavaScript. This is efficient for top-level requests. ```html ``` -------------------------------- ### Globally Enable Key Serialization with SWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/docs/middleware.es.mdx Configure SWR globally to use the serialize middleware for all SWR hooks by providing it in the SWRConfig value. ```jsx ``` -------------------------------- ### Pre-rendering with getStaticProps and SWR Fallback Source: https://github.com/vercel/swr-site/blob/main/content/docs/with-nextjs.mdx Use `getStaticProps` to pre-render a page and provide initial data via `fallback` in `SWRConfig`. The `Article` component will render pre-generated data first, then fetch the latest data after hydration. ```jsx export async function getStaticProps () { // `getStaticProps` is executed on the server side. const article = await getArticleFromAPI() return { props: { fallback: { '/api/article': article } } } } function Article() { // `data` will always be available as it's in `fallback`. const { data } = useSWR('/api/article', fetcher) return

{data.title}

} export default function Page({ fallback }) { // SWR hooks inside the `SWRConfig` boundary will use those values. return (
) } ``` -------------------------------- ### Typing useSWRSubscription with Options Source: https://github.com/vercel/swr-site/blob/main/content/docs/typescript.es.mdx Shows how to manually specify the type of the `next` callback argument within `SWRSubscriptionOptions` for `useSWRSubscription`. ```typescript 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` } } ``` -------------------------------- ### Configure Fallback Data with SWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Provide pre-fetched data as initial values for SWR hooks using the `fallback` option within `SWRConfig`. This is useful for SSG, SSR, and testing. ```jsx ``` -------------------------------- ### Prefetch Data in Server Components with SWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/docs/with-nextjs.es.mdx Initiate data fetching on the server in React Server Components and pass the resulting promises to client components via the `` provider's `fallback` option. This allows SWR to resolve promises during SSR. ```tsx import { SWRConfig } from 'swr' export default async function Layout({ children }: { children: React.ReactNode }) { // Initiate the data fetching on the server side. const userPromise = fetchUserFromAPI() const postsPromise = fetchPostsFromAPI() return ( {children} ) } ``` -------------------------------- ### Preload data with SWR Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v2.ko.mdx Use the preload API to fetch resources early, which useSWR will reuse if the request is still ongoing. ```jsx import useSWR, { preload } from 'swr' const fetcher = (url) => fetch(url).then((res) => res.json()) // You can call the preload function in anywhere preload('/api/user', fetcher) function Profile() { // The component that actually uses the data: const { data, error } = useSWR('/api/user', fetcher) // ... } export function Page () { return } ``` -------------------------------- ### Wrap components with SWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/docs/global-configuration.mdx Use SWRConfig to provide global configuration options to all child SWR hooks. ```jsx ``` -------------------------------- ### Apply Middleware with SWRConfig or useSWR Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Extend SWR's functionality by applying middleware globally via `SWRConfig` or locally to a specific hook instance. Middleware can be used for logging, caching strategies, and more. ```jsx // ... or directly in `useSWR`: useSWR(key, fetcher, { use: [...middleware] }) ``` -------------------------------- ### Programmatic Data Prefetching with SWR `preload` API Source: https://github.com/vercel/swr-site/blob/main/content/docs/prefetching.mdx Prefetch resources programmatically using the `preload` API, which accepts a `key` and a `fetcher`. This can be called outside of React components to prevent potential waterfalls. ```jsx import { useState } from 'react' import useSWR, { preload } from 'swr' const fetcher = (url) => fetch(url).then((res) => res.json()) // Preload the resource before rendering the User component below, // this prevents potential waterfalls in your application. // You can also start preloading when hovering the button or link, too. preload('/api/user', fetcher) function User() { const { data } = useSWR('/api/user', fetcher) ... } export default function App() { const [show, setShow] = useState(false) return (
{show ? : null}
) } ``` -------------------------------- ### Use Hook-Returned Mutate with useSWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.mdx It is now recommended to use the `mutate` function returned by the `useSWRConfig` hook instead of importing it globally. This ensures proper cache management, especially when using cache providers. ```diff - import { mutate } from 'swr' + import { useSWRConfig } from 'swr' ``` ```javascript function Foo () { const { mutate } = useSWRConfig() return } ``` -------------------------------- ### Chaining Middleware Configuration Source: https://github.com/vercel/swr-site/blob/main/content/docs/middleware.es.mdx Middleware options are extended like regular options. Nested SWRConfig providers with 'use' options will merge their middleware arrays. ```jsx function Bar () { useSWR(key, fetcher, { use: [c] }) // ... } function Foo() { return ( ) } ``` ```js useSWR(key, fetcher, { use: [a, b, c] }) ``` -------------------------------- ### Configure SWR Globally Source: https://context7.com/vercel/swr-site/llms.txt Use SWRConfig to provide default fetchers, error handlers, and fallback data to all hooks in the component tree. Nested providers can access and extend parent configurations. ```jsx import useSWR, { SWRConfig } from 'swr' // Global fetcher const globalFetcher = async (url) => { const res = await fetch(url, { headers: { 'Authorization': `Bearer ${getToken()}` } }) if (!res.ok) { const error = new Error('API request failed') error.status = res.status error.info = await res.json() throw error } return res.json() } function App() { return ( { if (error.status === 401) { redirectToLogin() } console.error(`SWR Error [${key}]:`, error) }, // Global success handler onSuccess: (data, key) => { console.log(`SWR Success [${key}]`) }, // Fallback data for SSR/SSG fallback: { '/api/config': { theme: 'light', locale: 'en' } } }} > ) } // Nested configuration (merges with parent) function AdminSection() { return ( ({ ...parentConfig, refreshInterval: 5000, // Override for admin section fetcher: (url) => parentConfig.fetcher(url, { admin: true }) })} > ) } ``` -------------------------------- ### Optimistic Updates with useSWRMutation Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.es.mdx Demonstrates how to configure optimistic data updates either globally in the hook options or specifically when calling the `trigger` function. ```jsx const { trigger } = useSWRMutation('/api/user', updateUser, { optimisticData: current => ({ ...current, name: newName }) }) // or trigger(newName, { optimisticData: current => ({ ...current, name: newName }) }) ``` -------------------------------- ### Perform basic mutation with request body Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.mdx Shows how to pass a request body to the fetcher and handle the mutation result using the trigger function. ```tsx import useSWRMutation from 'swr/mutation' async function sendRequest(url, { arg }: { arg: { username: string }}) { return fetch(url, { method: 'POST', body: JSON.stringify(arg) }).then(res => res.json()) } function App() { const { trigger, isMutating } = useSWRMutation('/api/user', sendRequest, /* options */) return ( ) } ``` -------------------------------- ### Extend SWR Configurations with Functions Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v2.es.mdx Configure SWR dynamically by providing a function to the `value` prop of `SWRConfig`. This function receives the parent configuration and returns a new one, allowing for flexible configuration inheritance in large codebases. ```jsx ({ dedupingInterval: parentConfig.dedupingInterval * 5, refreshInterval: 100, })}> ``` -------------------------------- ### Displaying Loading and Revalidation States with SWR Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/understanding.es.mdx Uses 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} ); } ``` -------------------------------- ### Implement SWR Middleware Source: https://context7.com/vercel/swr-site/llms.txt Create custom middleware functions to intercept SWR hooks and apply logic like logging or data persistence. Use the 'use' property in SWRConfig or individual useSWR hooks to apply them. ```jsx import useSWR, { SWRConfig } from 'swr' // Logger middleware function logger(useSWRNext) { return (key, fetcher, config) => { const extendedFetcher = async (...args) => { console.log(`[SWR] Fetching: ${key}`) const start = Date.now() try { const result = await fetcher(...args) console.log(`[SWR] Success: ${key} (${Date.now() - start}ms)`) return result } catch (error) { console.error(`[SWR] Error: ${key}`, error) throw error } } return useSWRNext(key, extendedFetcher, config) } } // Laggy data middleware - keep previous data while loading new key function laggy(useSWRNext) { return (key, fetcher, config) => { const laggyDataRef = useRef() const swr = useSWRNext(key, fetcher, config) useEffect(() => { if (swr.data !== undefined) { laggyDataRef.current = swr.data } }, [swr.data]) const dataOrLaggyData = swr.data === undefined ? laggyDataRef.current : swr.data const isLagging = swr.data === undefined && laggyDataRef.current !== undefined return { ...swr, data: dataOrLaggyData, isLagging } } } // Using middleware function App() { return ( ) } function SearchComponent() { const [query, setQuery] = useState('') // Use laggy middleware for smooth transitions const { data, isLagging } = useSWR( query ? `/api/search?q=${query}` : null, fetcher, { use: [laggy] } ) return (
setQuery(e.target.value)} /> {isLagging && Loading new results...} {data?.results.map(item =>
{item.title}
)}
) } ``` -------------------------------- ### useSWRMutation for Creating Users Source: https://github.com/vercel/swr-site/blob/main/content/docs/mutation.es.mdx Shows how to use useSWRMutation to send data to an API for user creation. The `isMutating` flag can be used to disable buttons during the request. ```tsx import useSWRMutation from 'swr/mutation' async function sendRequest(url, { arg }: { arg: { username: string } }) { return fetch(url, { method: 'POST', body: JSON.stringify(arg) }).then(res => res.json()) } function App() { const { trigger, isMutating } = useSWRMutation('/api/user', sendRequest, /* options */) return ( ) } ``` -------------------------------- ### Create a SWR Key Serialization Middleware Source: https://github.com/vercel/swr-site/blob/main/content/docs/middleware.es.mdx This middleware serializes array keys using JSON.stringify to ensure stable comparisons. It's useful for SWR versions older than 1.1.0. ```jsx function serialize(useSWRNext) { return (key, fetcher, config) => { // Serialize the key. const serializedKey = Array.isArray(key) ? JSON.stringify(key) : key // Pass the serialized key, and unserialize it in fetcher. return useSWRNext(serializedKey, (k) => fetcher(...JSON.parse(k)), config) } } ``` -------------------------------- ### Access Global Configurations with useSWRConfig Source: https://github.com/vercel/swr-site/blob/main/content/blog/swr-v1.es.mdx Retrieve global configurations, including the cache provider and `mutate` function, using the `useSWRConfig` hook. This is useful for interacting with global SWR state. ```javascript import { useSWRConfig } from 'swr' function Foo () { const { refreshInterval, cache, mutate, ...restConfig } = useSWRConfig() // ... } ``` -------------------------------- ### Global SWR Configuration Source: https://github.com/vercel/swr-site/blob/main/content/docs/advanced/react-native.mdx Wrap your application with SWRConfig to set default configurations globally. This is useful for applying settings across your entire app. ```jsx ```