22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/examples/subscription/README.md:
--------------------------------------------------------------------------------
1 | # Subscription
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/subscription)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/subscription
15 | cd subscription
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how you could use SWR to subscribe async observable data into your app.
31 |
--------------------------------------------------------------------------------
/src/_internal/utils/subscribe-key.ts:
--------------------------------------------------------------------------------
1 | type Callback = (...args: any[]) => any
2 |
3 | // Add a callback function to a list of keyed callback functions and return
4 | // the unsubscribe function.
5 | export const subscribeCallback = (
6 | key: string,
7 | callbacks: Record,
8 | callback: Callback
9 | ) => {
10 | const keyedRevalidators = callbacks[key] || (callbacks[key] = [])
11 | keyedRevalidators.push(callback)
12 |
13 | return () => {
14 | const index = keyedRevalidators.indexOf(callback)
15 |
16 | if (index >= 0) {
17 | // O(1): faster than splice
18 | keyedRevalidators[index] = keyedRevalidators[keyedRevalidators.length - 1]
19 | keyedRevalidators.pop()
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/axios-typescript/pages/api/data.ts:
--------------------------------------------------------------------------------
1 | import { NextApiRequest, NextApiResponse } from 'next'
2 | import axios from 'axios'
3 |
4 | const projects = [
5 | 'facebook/flipper',
6 | 'vuejs/vuepress',
7 | 'rust-lang/rust',
8 | 'vercel/next.js'
9 | ]
10 |
11 | export default function api(req: NextApiRequest, res: NextApiResponse) {
12 | if (req.query.id) {
13 | // a slow endpoint for getting repo data
14 | axios(`https://api.github.com/repos/${req.query.id}`)
15 | .then(response => response.data)
16 | .then(data => {
17 | setTimeout(() => {
18 | res.json(data)
19 | }, 2000)
20 | })
21 |
22 | return
23 | }
24 | setTimeout(() => {
25 | res.json(projects)
26 | }, 2000)
27 | }
28 |
--------------------------------------------------------------------------------
/examples/local-state-sharing/README.md:
--------------------------------------------------------------------------------
1 | # Basic
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/local-state-sharing)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/local-state-sharing
15 | cd local-state-sharing
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how to share local state between React components using SWR.
31 |
--------------------------------------------------------------------------------
/examples/basic/pages/[user]/[repo].js:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import fetch from '../../libs/fetch'
3 |
4 | import useSWR from 'swr'
5 |
6 | export default function Repo() {
7 | const id = typeof window !== 'undefined' ? window.location.pathname.slice(1) : ''
8 | const { data } = useSWR('/api/data?id=' + id, fetch)
9 |
10 | return (
11 |
12 |
{id}
13 | {
14 | data ?
15 |
forks: {data.forks_count}
16 |
stars: {data.stargazers_count}
17 |
watchers: {data.watchers}
18 |
: 'loading...'
19 | }
20 |
21 |
22 | Back
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/examples/global-fetcher/README.md:
--------------------------------------------------------------------------------
1 | # Global Fetcher
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/global-fetcher)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/global-fetcher
15 | cd global-fetcher
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Use the `SWRConfig` provider to set up the fetcher globally instead of a per-hook call.
31 |
--------------------------------------------------------------------------------
/examples/storage-tab-sync/README.md:
--------------------------------------------------------------------------------
1 | # Storage Tab Sync
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/storage-tab-sync)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/storage-tab-sync
15 | cd storage-tab-sync
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how you could use SWR to synchronize localStorage values between tabs.
31 |
--------------------------------------------------------------------------------
/src/_internal/utils/merge-config.ts:
--------------------------------------------------------------------------------
1 | import { mergeObjects } from './shared'
2 | import type { FullConfiguration } from '../types'
3 |
4 | export const mergeConfigs = (
5 | a: Partial,
6 | b?: Partial
7 | ) => {
8 | // Need to create a new object to avoid mutating the original here.
9 | const v: Partial = mergeObjects(a, b)
10 |
11 | // If two configs are provided, merge their `use` and `fallback` options.
12 | if (b) {
13 | const { use: u1, fallback: f1 } = a
14 | const { use: u2, fallback: f2 } = b
15 | if (u1 && u2) {
16 | v.use = u1.concat(u2)
17 | }
18 | if (f1 && f2) {
19 | v.fallback = mergeObjects(f1, f2)
20 | }
21 | }
22 |
23 | return v
24 | }
25 |
--------------------------------------------------------------------------------
/examples/basic-typescript/README.md:
--------------------------------------------------------------------------------
1 | # Basic TypeScript
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/basic-typescript)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/basic-typescript
15 | cd basic-typescript
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how to use the basic example along with TypeScript to type the data received from SWR.
31 |
--------------------------------------------------------------------------------
/examples/api-hooks/README.md:
--------------------------------------------------------------------------------
1 | # API Hooks
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/api-hooks)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/api-hooks
15 | cd api-hooks
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how you could create custom hooks, using SWR internally, for your different data requirements and use them in your application.
31 |
--------------------------------------------------------------------------------
/examples/basic-typescript/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import fetch from '../libs/fetch'
3 |
4 | import useSWR from 'swr'
5 |
6 | export default function HomePage() {
7 | const { data } = useSWR('/api/data', fetch)
8 | const { data: data2 } = useSWR(null, fetch)
9 |
10 | return (
11 |
12 |
Trending Projects
13 | {data2}
14 |
15 | {data
16 | ? data.map(project => (
17 |
18 |
19 | {project}
20 |
21 |
22 | ))
23 | : 'loading...'}
24 |
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/examples/autocomplete-suggestions/README.md:
--------------------------------------------------------------------------------
1 | # Autocomplete Suggestions
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/autocomplete-suggestions)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/autocomplete-suggestions
15 | cd autocomplete-suggestions
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how to use SWR to fetch the suggestion for an autocomplete.
31 |
--------------------------------------------------------------------------------
/examples/refetch-interval/README.md:
--------------------------------------------------------------------------------
1 | # Refetch Interval
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel Now.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/refetch-interval)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/refetch-interval
15 | cd refetch-interval
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how to make SWR fetch the API again in an interval automatically to ensure the data is up-to-date.
31 |
--------------------------------------------------------------------------------
/examples/axios-typescript/README.md:
--------------------------------------------------------------------------------
1 | # Axios TypeScript
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/axios-typescript)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/axios-typescript
15 | cd axios-typescript
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show how to use the basic axios along with TypeScript to type both the request object and the data received from SWR.
31 |
--------------------------------------------------------------------------------
/examples/infinite-scroll/README.md:
--------------------------------------------------------------------------------
1 | # useSWRInfinite with scroll based on IntersectionObserver
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/infinite-scroll)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/infinite-scroll
15 | cd infinite-scroll
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Show usage of useSWRInfinite with infinite scroll based on IntersectionObserver
31 |
--------------------------------------------------------------------------------
/examples/suspense/pages/api/data.js:
--------------------------------------------------------------------------------
1 | const projects = [
2 | 'facebook/flipper',
3 | 'vuejs/vuepress',
4 | 'rust-lang/rust',
5 | 'vercel/next.js',
6 | 'emperor/clothes'
7 | ]
8 |
9 | export default function api(req, res) {
10 | if (req.query.id) {
11 | if (req.query.id === projects[4]) {
12 | setTimeout(() => {
13 | res.json({ msg: 'not found' })
14 | })
15 | } else {
16 | // a slow endpoint for getting repo data
17 | fetch(`https://api.github.com/repos/${req.query.id}`)
18 | .then(res => res.json())
19 | .then(data => {
20 | setTimeout(() => {
21 | res.json(data)
22 | }, 2000)
23 | })
24 | }
25 | } else {
26 | setTimeout(() => {
27 | res.json(projects)
28 | }, 2000)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/_internal/utils/serialize.ts:
--------------------------------------------------------------------------------
1 | import { stableHash } from './hash'
2 | import { isFunction } from './shared'
3 |
4 | import type { Key, Arguments } from '../types'
5 |
6 | export const serialize = (key: Key): [string, Arguments] => {
7 | if (isFunction(key)) {
8 | try {
9 | key = key()
10 | } catch (err) {
11 | // dependencies not ready
12 | key = ''
13 | }
14 | }
15 |
16 | // Use the original key as the argument of fetcher. This can be a string or an
17 | // array of values.
18 | const args = key
19 |
20 | // If key is not falsy, or not an empty array, hash it.
21 | key =
22 | typeof key == 'string'
23 | ? key
24 | : (Array.isArray(key) ? key.length : key)
25 | ? stableHash(key)
26 | : ''
27 |
28 | return [key, args]
29 | }
30 |
--------------------------------------------------------------------------------
/e2e/test/suspense-undefined-key.test.ts:
--------------------------------------------------------------------------------
1 | import { test, expect } from '@playwright/test'
2 |
3 | test.describe('suspense with undefined key', () => {
4 | test('should render correctly when key is undefined', async ({ page }) => {
5 | await page.goto('./suspense-undefined-key', { waitUntil: 'commit' })
6 |
7 | // Should show content for undefined key (not suspense)
8 | await expect(page.getByText('empty')).toBeVisible()
9 |
10 | // Click toggle to enable key
11 | await page.getByRole('button', { name: 'toggle' }).click()
12 |
13 | // Should show loading fallback when key becomes defined
14 | await expect(page.getByText('fallback')).toBeVisible()
15 |
16 | // Should eventually show the fetched data
17 | await expect(page.getByText('SWR')).toBeVisible()
18 | })
19 | })
20 |
--------------------------------------------------------------------------------
/examples/suspense-retry/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "plugins": [
18 | {
19 | "name": "next"
20 | }
21 | ],
22 | "baseUrl": ".",
23 | "paths": {
24 | "~/*": ["./*"]
25 | }
26 | },
27 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
28 | "exclude": ["node_modules"]
29 | }
30 |
--------------------------------------------------------------------------------
/src/_internal/utils/with-middleware.ts:
--------------------------------------------------------------------------------
1 | import { normalize } from './normalize-args'
2 |
3 | import type {
4 | Key,
5 | Fetcher,
6 | Middleware,
7 | SWRConfiguration,
8 | SWRHook
9 | } from '../types'
10 |
11 | // Create a custom hook with a middleware
12 | export const withMiddleware = (
13 | useSWR: SWRHook,
14 | middleware: Middleware
15 | ): SWRHook => {
16 | return (
17 | ...args:
18 | | [Key]
19 | | [Key, Fetcher | null]
20 | | [Key, SWRConfiguration | undefined]
21 | | [Key, Fetcher | null, SWRConfiguration | undefined]
22 | ) => {
23 | const [key, fn, config] = normalize(args)
24 | const uses = (config.use || []).concat(middleware)
25 | return useSWR(key, fn, { ...config, use: uses })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/examples/focus-revalidate/README.md:
--------------------------------------------------------------------------------
1 | # Focus Revalidate
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/focus-revalidate)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/focus-revalidate
15 | cd focus-revalidate
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Basic authentication example showing how the revalidate on focus feature works and to trigger a revalidation on a per-hook call basis.
31 |
--------------------------------------------------------------------------------
/e2e/site/app/concurrent-transition/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { Suspense } from 'react'
4 | import dynamic from 'next/dynamic'
5 |
6 | const TransitionDemo = dynamic(() => import('./transition-demo'), {
7 | ssr: false
8 | })
9 |
10 | export default function ConcurrentTransitionPage() {
11 | return (
12 |
13 |
React 19 Concurrent Transition Test
14 |
15 | This page tests SWR's behavior with React 19 concurrent
16 | transitions. When using useTransition, SWR should "pause"
17 | loading states to provide smooth UX.
18 |
19 | Loading page...
}>
20 |
21 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/examples/optimistic-ui/README.md:
--------------------------------------------------------------------------------
1 | # Optimistic UI
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/optimistic-ui)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/optimistic-ui
15 | cd optimistic-ui
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Example of how to use SWR to implement an Optimistic UI pattern where we mutate the cached data immediately and then trigger a revalidation with the API.
31 |
--------------------------------------------------------------------------------
/examples/suspense-global/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "noImplicitAny": true,
18 | "plugins": [
19 | {
20 | "name": "next"
21 | }
22 | ],
23 | "baseUrl": ".",
24 | "paths": {
25 | "~/*": ["./*"]
26 | }
27 | },
28 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
29 | "exclude": ["node_modules"]
30 | }
31 |
--------------------------------------------------------------------------------
/examples/focus-revalidate/pages/index.js:
--------------------------------------------------------------------------------
1 | import Button from '../components/button'
2 | import fetch from '../libs/fetch'
3 | import { login, logout } from '../libs/auth'
4 |
5 | import useSWR from 'swr'
6 |
7 | export default function Index() {
8 | const { data, mutate } = useSWR('/api/user', fetch)
9 |
10 | if (!data) return
loading...
11 | if (data.loggedIn) {
12 | return
13 |
Welcome, {data.name}
14 |
15 |
19 |
20 | } else {
21 | return
22 |
Please login
23 |
27 |
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/examples/optimistic-ui-immer/README.md:
--------------------------------------------------------------------------------
1 | # Optimistic UI with Immer
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/optimistic-ui-immer)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/optimistic-ui-immer
15 | cd optimistic-ui-immer
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | Example of how to use SWR and Immer to implement an Optimistic UI pattern where we mutate the cached data immediately and then trigger a revalidation with the API.
31 |
--------------------------------------------------------------------------------
/e2e/site/app/suspense-undefined-key/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { Suspense, useReducer } from 'react'
4 | import useSWR from 'swr'
5 |
6 | const fetcher = async (key: string) => {
7 | // Add a small delay to simulate network request
8 | await new Promise(resolve => setTimeout(resolve, 100))
9 | return 'SWR'
10 | }
11 |
12 | const Section = ({ trigger }: { trigger: boolean }) => {
13 | const { data } = useSWR(trigger ? 'test-key' : undefined, fetcher, {
14 | suspense: true
15 | })
16 | return
}>
35 |
36 |
37 |
38 |
39 | )
40 | }
41 |
42 | export default RemoteData
43 |
--------------------------------------------------------------------------------
/examples/server-render/README.md:
--------------------------------------------------------------------------------
1 | # Server Render
2 |
3 | ## One-Click Deploy
4 |
5 | Deploy your own SWR project with Vercel.
6 |
7 | [](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/server-render)
8 |
9 | ## How to Use
10 |
11 | Download the example:
12 |
13 | ```bash
14 | curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/server-render
15 | cd server-render
16 | ```
17 |
18 | Install it and run:
19 |
20 | ```bash
21 | yarn
22 | yarn dev
23 | # or
24 | npm install
25 | npm run dev
26 | ```
27 |
28 | ## The Idea behind the Example
29 |
30 | This example shows how to combine Next.js getServerSideProps with the SWR `fallbackData` option to support Server-Side Rendering.
31 |
32 | The application will fetch the data server-side and then receive it as props, that data will be passed as `fallbackData` to SWR, once the application starts client-side SWR will revalidate it against the API and update the DOM, if it's required, with the new data.
33 |
--------------------------------------------------------------------------------
/e2e/site/app/suspense-retry/manual-retry.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 | import { Suspense } from 'react'
3 | import { ErrorBoundary } from 'react-error-boundary'
4 | import { useRemoteData, preloadRemote } from './use-remote-data'
5 |
6 | const Demo = () => {
7 | const { data } = useRemoteData()
8 | return
21 | }
22 |
23 | renderWithConfig()
24 |
25 | screen.getByText('data:')
26 | await act(() => sleep(100))
27 | screen.getByText('data:0')
28 | })
29 |
30 | // https://codesandbox.io/s/concurrent-swr-case-ii-lr6x4u
31 | it.skip('should do state updates in transitions', async () => {
32 | const key1 = createKey()
33 | const key2 = createKey()
34 |
35 | const log = []
36 |
37 | function Counter() {
38 | const [count, setCount] = React.useState(0)
39 |
40 | React.useEffect(() => {
41 | const interval = setInterval(() => {
42 | setCount(x => x + 1)
43 | }, 20)
44 | return () => clearInterval(interval)
45 | }, [])
46 |
47 | log.push(count)
48 |
49 | return <>{count}>
50 | }
51 |
52 | function Body() {
53 | useSWR(key2, () => createResponse(true, { delay: 1000 }), {
54 | revalidateOnFocus: false,
55 | revalidateOnReconnect: false,
56 | dedupingInterval: 0,
57 | suspense: true
58 | })
59 | return null
60 | }
61 |
62 | function Page() {
63 | const { data } = useSWR(key1, () => createResponse(true, { delay: 50 }), {
64 | revalidateOnFocus: false,
65 | revalidateOnReconnect: false,
66 | dedupingInterval: 0
67 | })
68 |
69 | return (
70 | <>
71 |
72 | {data ? : null}
73 | >
74 | )
75 | }
76 |
77 | await executeWithoutBatching(async () => {
78 | renderWithConfig()
79 | await sleep(500)
80 | })
81 | })
82 | })
83 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # SWR Contribution Guidelines
2 |
3 | Thank you for reading this guide and we appreciate any contribution.
4 |
5 | ## Ask a Question
6 |
7 | You can use the repository's [Discussions](https://github.com/vercel/swr/discussions) page to ask any questions, post feedback, or share your experience on how you use this library.
8 |
9 | ## Report a Bug
10 |
11 | Whenever you find something which is not working properly, please first search the repository's [Issues](https://github.com/vercel/swr/issues) page and make sure it's not reported by someone else already.
12 |
13 | If not, feel free to open an issue with a detailed description of the problem and the expected behavior. And reproduction (for example a [CodeSandbox](https://codesandbox.io) link) will be extremely helpful.
14 |
15 | ## Request for a New Feature
16 |
17 | For new features, it would be great to have some discussions from the community before starting working on it. You can either create an issue (if there isn't one) or post a thread on the [Discussions](https://github.com/vercel/swr/discussions) page to describe the feature that you want to have.
18 |
19 | If possible, you can add another additional context like how this feature can be implemented technically, what other alternative solutions we can have, etc.
20 |
21 | ## Open a PR for Bugfix or Feature
22 |
23 | ### Local Development with Examples
24 |
25 | To run SWR locally, you can start it with any example in the `examples` folder. You need to set up the example and run the command in the root directory for overriding SWR and its dependencies to local assets.
26 |
27 | First of all, build SWR assets
28 |
29 | ```sh
30 | corepack enable
31 | corepack pnpm install
32 |
33 | pnpm watch
34 | ```
35 |
36 | Install dependency of the target example, for instance `examples/basic`:
37 |
38 |
39 | ```sh
40 | # by default it will run next dev for the example
41 | pnpm next dev examples/basic
42 | ```
43 |
44 | All examples are built with Next.js, so Next.js commands are all supported:
45 |
46 | ```sh
47 | # if you want to build and start
48 | pnpm next build examples/basic
49 | pnpm next start examples/basic
50 | ```
51 | ## Update Documentation
52 |
53 | To update the [SWR Documentation](https://swr.vercel.app), you can contribute to the [website repository](https://github.com/vercel/swr-site).
54 |
--------------------------------------------------------------------------------
/examples/infinite/pages/index.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import useSWRInfinite from 'swr/infinite'
3 |
4 | import fetch from '../libs/fetch'
5 |
6 | const PAGE_SIZE = 6
7 |
8 | export default function App() {
9 | const [repo, setRepo] = useState('reactjs/react-a11y')
10 | const [val, setVal] = useState(repo)
11 |
12 | const { data, error, mutate, size, setSize, isValidating } = useSWRInfinite(
13 | (index) =>
14 | `https://api.github.com/repos/${repo}/issues?per_page=${PAGE_SIZE}&page=${
15 | index + 1
16 | }`,
17 | fetch
18 | )
19 |
20 | const issues = data ? [].concat(...data) : []
21 | const isLoadingInitialData = !data && !error
22 | const isLoadingMore =
23 | isLoadingInitialData ||
24 | (size > 0 && data && typeof data[size - 1] === 'undefined')
25 | const isEmpty = data?.[0]?.length === 0
26 | const isReachingEnd =
27 | isEmpty || (data && data[data.length - 1]?.length < PAGE_SIZE)
28 | const isRefreshing = isValidating && data && data.length === size
29 |
30 | return (
31 |