### 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 {user.name} } ``` -------------------------------- ### 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

{totalUsers} users listed

{data.map((users, index) => { return users.map(user =>
{user.name}
) })}
} ``` ### 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 (
setSearch(e.target.value)} placeholder="Search..." />
{data?.products.map(item => )
); } ``` -------------------------------- ### 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 {user.name} } ``` -------------------------------- ### 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 ```