├── .github
├── CODEOWNERS
├── pull_request_template.md
└── videos
│ ├── fast-navigation.mp4
│ ├── focus-revalidate.mp4
│ ├── local-mutation.mp4
│ ├── refetch-interval.mp4
│ └── swr-pages.mp4
├── .gitignore
├── README.md
├── components
├── authors.js
├── blog-index.js
├── diagrams
│ ├── cache.js
│ ├── infinite.js
│ ├── pagination.js
│ └── welcome.js
├── excalidraw
│ └── state-machine.excalidraw
├── features.js
├── features.module.css
├── icons
│ ├── backend-agnostic.js
│ ├── lightweight.js
│ ├── pagination.js
│ ├── realtime.js
│ ├── remote-local.js
│ ├── rendering-strategies.js
│ ├── suspense.js
│ └── typescript.js
├── logo.js
├── use-locales-map.js
├── vercel.js
└── video.js
├── jsconfig.json
├── license.md
├── middleware.js
├── next.config.js
├── package.json
├── pages
├── _app.mdx
├── _document.js
├── _meta.en-US.json
├── _meta.es-ES.json
├── _meta.fr-FR.json
├── _meta.ja.json
├── _meta.ko.json
├── _meta.pt-BR.json
├── _meta.ru.json
├── _meta.zh-CN.json
├── blog.en-US.mdx
├── blog.es-ES.mdx
├── blog.fr-FR.mdx
├── blog.ja.mdx
├── blog.ko.mdx
├── blog.pt-BR.mdx
├── blog.ru.mdx
├── blog.zh-CN.mdx
├── blog
│ ├── _meta.en-US.json
│ ├── _meta.es-ES.json
│ ├── _meta.fr-FR.json
│ ├── _meta.ja.json
│ ├── _meta.ko.json
│ ├── _meta.pt-BR.json
│ ├── _meta.ru.json
│ ├── _meta.zh-CN.json
│ ├── swr-v1.en-US.mdx
│ ├── swr-v1.es-ES.mdx
│ ├── swr-v1.fr-FR.mdx
│ ├── swr-v1.ja.mdx
│ ├── swr-v1.ko.mdx
│ ├── swr-v1.pt-BR.mdx
│ ├── swr-v1.ru.mdx
│ ├── swr-v1.zh-CN.mdx
│ ├── swr-v2.en-US.mdx
│ ├── swr-v2.es-ES.mdx
│ ├── swr-v2.fr-FR.mdx
│ ├── swr-v2.ja.mdx
│ ├── swr-v2.ko.mdx
│ ├── swr-v2.pt-BR.mdx
│ ├── swr-v2.ru.mdx
│ └── swr-v2.zh-CN.mdx
├── docs
│ ├── _meta.en-US.json
│ ├── _meta.es-ES.json
│ ├── _meta.fr-FR.json
│ ├── _meta.ja.json
│ ├── _meta.ko.json
│ ├── _meta.pt-BR.json
│ ├── _meta.ru.json
│ ├── _meta.zh-CN.json
│ ├── advanced
│ │ ├── _meta.en-US.json
│ │ ├── _meta.es-ES.json
│ │ ├── _meta.fr-FR.json
│ │ ├── _meta.ja.json
│ │ ├── _meta.ko.json
│ │ ├── _meta.pt-BR.json
│ │ ├── _meta.ru.json
│ │ ├── _meta.zh-CN.json
│ │ ├── cache.en-US.mdx
│ │ ├── cache.es-ES.mdx
│ │ ├── cache.fr-FR.mdx
│ │ ├── cache.ja.mdx
│ │ ├── cache.ko.mdx
│ │ ├── cache.pt-BR.mdx
│ │ ├── cache.ru.mdx
│ │ ├── cache.zh-CN.mdx
│ │ ├── devtools.en-US.mdx
│ │ ├── devtools.es-ES.mdx
│ │ ├── devtools.fr-FR.mdx
│ │ ├── devtools.ja.mdx
│ │ ├── devtools.ko.mdx
│ │ ├── devtools.pt-BR.mdx
│ │ ├── devtools.ru.mdx
│ │ ├── devtools.zh-CN.mdx
│ │ ├── performance.en-US.mdx
│ │ ├── performance.es-ES.mdx
│ │ ├── performance.fr-FR.mdx
│ │ ├── performance.ja.mdx
│ │ ├── performance.ko.mdx
│ │ ├── performance.pt-BR.mdx
│ │ ├── performance.ru.mdx
│ │ ├── performance.zh-CN.mdx
│ │ ├── react-native.en-US.mdx
│ │ ├── react-native.es-ES.mdx
│ │ ├── react-native.fr-FR.mdx
│ │ ├── react-native.ja.mdx
│ │ ├── react-native.ko.mdx
│ │ ├── react-native.pt-BR.mdx
│ │ ├── react-native.ru.mdx
│ │ ├── react-native.zh-CN.mdx
│ │ ├── understanding.en-US.mdx
│ │ ├── understanding.es-ES.mdx
│ │ ├── understanding.fr-FR.mdx
│ │ ├── understanding.ja.mdx
│ │ ├── understanding.ko.mdx
│ │ ├── understanding.pt-BR.mdx
│ │ ├── understanding.ru.mdx
│ │ └── understanding.zh-CN.mdx
│ ├── api.en-US.mdx
│ ├── api.es-ES.mdx
│ ├── api.fr-FR.mdx
│ ├── api.ja.mdx
│ ├── api.ko.mdx
│ ├── api.pt-BR.mdx
│ ├── api.ru.mdx
│ ├── api.zh-CN.mdx
│ ├── arguments.en-US.mdx
│ ├── arguments.es-ES.mdx
│ ├── arguments.fr-FR.mdx
│ ├── arguments.ja.mdx
│ ├── arguments.ko.mdx
│ ├── arguments.pt-BR.mdx
│ ├── arguments.ru.mdx
│ ├── arguments.zh-CN.mdx
│ ├── conditional-fetching.en-US.mdx
│ ├── conditional-fetching.es-ES.mdx
│ ├── conditional-fetching.fr-FR.mdx
│ ├── conditional-fetching.ja.mdx
│ ├── conditional-fetching.ko.mdx
│ ├── conditional-fetching.pt-BR.mdx
│ ├── conditional-fetching.ru.mdx
│ ├── conditional-fetching.zh-CN.mdx
│ ├── data-fetching.en-US.mdx
│ ├── data-fetching.es-ES.mdx
│ ├── data-fetching.fr-FR.mdx
│ ├── data-fetching.ja.mdx
│ ├── data-fetching.ko.mdx
│ ├── data-fetching.pt-BR.mdx
│ ├── data-fetching.ru.mdx
│ ├── data-fetching.zh-CN.mdx
│ ├── error-handling.en-US.mdx
│ ├── error-handling.es-ES.mdx
│ ├── error-handling.fr-FR.mdx
│ ├── error-handling.ja.mdx
│ ├── error-handling.ko.mdx
│ ├── error-handling.pt-BR.mdx
│ ├── error-handling.ru.mdx
│ ├── error-handling.zh-CN.mdx
│ ├── getting-started.en-US.mdx
│ ├── getting-started.es-ES.mdx
│ ├── getting-started.fr-FR.mdx
│ ├── getting-started.ja.mdx
│ ├── getting-started.ko.mdx
│ ├── getting-started.pt-BR.mdx
│ ├── getting-started.ru.mdx
│ ├── getting-started.zh-CN.mdx
│ ├── global-configuration.en-US.mdx
│ ├── global-configuration.es-ES.mdx
│ ├── global-configuration.fr-FR.mdx
│ ├── global-configuration.ja.mdx
│ ├── global-configuration.ko.mdx
│ ├── global-configuration.pt-BR.mdx
│ ├── global-configuration.ru.mdx
│ ├── global-configuration.zh-CN.mdx
│ ├── middleware.en-US.mdx
│ ├── middleware.es-ES.mdx
│ ├── middleware.fr-FR.mdx
│ ├── middleware.ja.mdx
│ ├── middleware.ko.mdx
│ ├── middleware.pt-BR.mdx
│ ├── middleware.ru.mdx
│ ├── middleware.zh-CN.mdx
│ ├── mutation.en-US.mdx
│ ├── mutation.es-ES.mdx
│ ├── mutation.fr-FR.mdx
│ ├── mutation.ja.mdx
│ ├── mutation.ko.mdx
│ ├── mutation.pt-BR.mdx
│ ├── mutation.ru.mdx
│ ├── mutation.zh-CN.mdx
│ ├── pagination.en-US.mdx
│ ├── pagination.es-ES.mdx
│ ├── pagination.fr-FR.mdx
│ ├── pagination.ja.mdx
│ ├── pagination.ko.mdx
│ ├── pagination.pt-BR.mdx
│ ├── pagination.ru.mdx
│ ├── pagination.zh-CN.mdx
│ ├── prefetching.en-US.mdx
│ ├── prefetching.es-ES.mdx
│ ├── prefetching.fr-FR.mdx
│ ├── prefetching.ja.mdx
│ ├── prefetching.ko.mdx
│ ├── prefetching.pt-BR.mdx
│ ├── prefetching.ru.mdx
│ ├── prefetching.zh-CN.mdx
│ ├── revalidation.en-US.mdx
│ ├── revalidation.es-ES.mdx
│ ├── revalidation.fr-FR.mdx
│ ├── revalidation.ja.mdx
│ ├── revalidation.ko.mdx
│ ├── revalidation.pt-BR.mdx
│ ├── revalidation.ru.mdx
│ ├── revalidation.zh-CN.mdx
│ ├── subscription.en-US.mdx
│ ├── subscription.es-ES.mdx
│ ├── subscription.fr-FR.mdx
│ ├── subscription.ja.mdx
│ ├── subscription.ko.mdx
│ ├── subscription.pt-BR.mdx
│ ├── subscription.ru.mdx
│ ├── subscription.zh-CN.mdx
│ ├── suspense.en-US.mdx
│ ├── suspense.es-ES.mdx
│ ├── suspense.fr-FR.mdx
│ ├── suspense.ja.mdx
│ ├── suspense.ko.mdx
│ ├── suspense.pt-BR.mdx
│ ├── suspense.ru.mdx
│ ├── suspense.zh-CN.mdx
│ ├── typescript.en-US.mdx
│ ├── typescript.es-ES.mdx
│ ├── typescript.fr-FR.mdx
│ ├── typescript.ja.mdx
│ ├── typescript.ko.mdx
│ ├── typescript.pt-BR.mdx
│ ├── typescript.ru.mdx
│ ├── typescript.zh-CN.mdx
│ ├── with-nextjs.en-US.mdx
│ ├── with-nextjs.es-ES.mdx
│ ├── with-nextjs.fr-FR.mdx
│ ├── with-nextjs.ja.mdx
│ ├── with-nextjs.ko.mdx
│ ├── with-nextjs.pt-BR.mdx
│ ├── with-nextjs.ru.mdx
│ └── with-nextjs.zh-CN.mdx
├── examples
│ ├── _meta.en-US.json
│ ├── _meta.es-ES.json
│ ├── _meta.fr-FR.json
│ ├── _meta.ja.json
│ ├── _meta.ko.json
│ ├── _meta.pt-BR.json
│ ├── _meta.ru.json
│ ├── _meta.zh-CN.json
│ ├── auth.en-US.mdx
│ ├── auth.es-ES.mdx
│ ├── auth.fr-FR.mdx
│ ├── auth.ja.mdx
│ ├── auth.ko.mdx
│ ├── auth.pt-BR.mdx
│ ├── auth.ru.mdx
│ ├── auth.zh-CN.mdx
│ ├── basic.en-US.mdx
│ ├── basic.es-ES.mdx
│ ├── basic.fr-FR.mdx
│ ├── basic.ja.mdx
│ ├── basic.ko.mdx
│ ├── basic.pt-BR.mdx
│ ├── basic.ru.mdx
│ ├── basic.zh-CN.mdx
│ ├── error-handling.en-US.mdx
│ ├── error-handling.es-ES.mdx
│ ├── error-handling.fr-FR.mdx
│ ├── error-handling.ja.mdx
│ ├── error-handling.ko.mdx
│ ├── error-handling.pt-BR.mdx
│ ├── error-handling.ru.mdx
│ ├── error-handling.zh-CN.mdx
│ ├── infinite-loading.en-US.mdx
│ ├── infinite-loading.es-ES.mdx
│ ├── infinite-loading.fr-FR.mdx
│ ├── infinite-loading.ja.mdx
│ ├── infinite-loading.ko.mdx
│ ├── infinite-loading.pt-BR.mdx
│ ├── infinite-loading.ru.mdx
│ ├── infinite-loading.zh-CN.mdx
│ ├── optimistic-ui.en-US.mdx
│ ├── optimistic-ui.es-ES.mdx
│ ├── optimistic-ui.fr-FR.mdx
│ ├── optimistic-ui.ja.mdx
│ ├── optimistic-ui.ko.mdx
│ ├── optimistic-ui.pt-BR.mdx
│ ├── optimistic-ui.ru.mdx
│ ├── optimistic-ui.zh-CN.mdx
│ ├── ssr.en-US.mdx
│ ├── ssr.es-ES.mdx
│ ├── ssr.fr-FR.mdx
│ ├── ssr.ja.mdx
│ ├── ssr.ko.mdx
│ ├── ssr.pt-BR.mdx
│ ├── ssr.ru.mdx
│ ├── ssr.zh-CN.mdx
│ ├── subscription.en-US.mdx
│ ├── subscription.es-ES.mdx
│ ├── subscription.fr-FR.mdx
│ ├── subscription.ja.mdx
│ ├── subscription.ko.mdx
│ ├── subscription.pt-BR.mdx
│ ├── subscription.ru.mdx
│ └── subscription.zh-CN.mdx
├── index.en-US.mdx
├── index.es-ES.mdx
├── index.fr-FR.mdx
├── index.ja.mdx
├── index.ko.mdx
├── index.pt-BR.mdx
├── index.ru.mdx
└── index.zh-CN.mdx
├── pnpm-lock.yaml
├── postcss.config.js
├── public
├── favicon
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── favicon.svg
│ ├── mstile-150x150.png
│ ├── safari-pinned-tab.svg
│ └── site.webmanifest
├── img
│ ├── devtools
│ │ └── cache-view.jpg
│ └── understanding
│ │ ├── fallback.svg
│ │ ├── fetch-and-revalidate.svg
│ │ ├── isloading.gif
│ │ ├── key-change-fallback.svg
│ │ ├── key-change-previous-data-fallback.svg
│ │ ├── key-change-previous-data.svg
│ │ └── key-change.svg
└── video
│ └── optimistic-ui.mp4
├── styles.css
├── tailwind.config.js
├── theme.config.js
└── translations
├── svgs.js
└── text.js
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @shuding @pacocoursey @huozhi
2 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 |
19 |
20 | ### Description
21 |
22 |
23 |
24 | - [ ] Adding new page
25 | - [ ] Updating existing documentation
26 | - [ ] Other updates
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.github/videos/fast-navigation.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/.github/videos/fast-navigation.mp4
--------------------------------------------------------------------------------
/.github/videos/focus-revalidate.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/.github/videos/focus-revalidate.mp4
--------------------------------------------------------------------------------
/.github/videos/local-mutation.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/.github/videos/local-mutation.mp4
--------------------------------------------------------------------------------
/.github/videos/refetch-interval.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/.github/videos/refetch-interval.mp4
--------------------------------------------------------------------------------
/.github/videos/swr-pages.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/.github/videos/swr-pages.mp4
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .next
3 | .DS_Store
4 | yarn-error.log
5 | .yalc
6 | yalc.lock
7 |
8 | public/*.st
9 | public/*.toml
10 | public/.nextra
11 | .vercel
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [SWR website](https://swr.vercel.app)
2 |
3 | The official website for [SWR](https://github.com/vercel/swr).
4 |
5 | The project uses [pnpm](https://pnpm.io), [Nextra](https://nextra.vercel.app) and deploys via [Vercel](https://vercel.com). To develop it locally, clone this repository and run the following command to start the local dev server:
6 |
7 | ```bash
8 | pnpm install
9 | pnpm dev
10 | ```
11 |
12 | And visit `localhost:3000` to preview your changes.
13 |
14 | ## Contributing
15 |
16 | When making a change, or creating a new page, please make sure to edit all language files. You can simply copy the content of the edited English document (or the edited paragraph) and apply it to other language files. And then, volunteers are welcome to help with any untranslated sections.
17 |
18 | ## Contributors
19 |
20 | - [https://github.com/vercel/swr-site/graphs/contributors](https://github.com/vercel/swr-site/graphs/contributors)
21 | - Simplified Chinese translation done by Fang Lu ([@huzhengen](https://github.com/huzhengen))
22 | - Spanish translation done by Markoz Peña ([@markozxuu](https://twitter.com/markozxuu))
23 | - Japanese translation done by uttk ([@uttk](https://github.com/uttk)), Tomohiro SHIOYA ([@shioyang](https://github.com/shioyang))
24 | - Korean translation done by SeulGi Choi ([@cs09g](https://github.com/cs09g))
25 | - Russian translation done by Valentin Politov ([@valentinpolitov](https://github.com/valentinpolitov))
26 | - Brazilian Portuguese translation done by Guilherme Sousa ([@guilherssousa](https://github.com/guilherssousa))
27 | - French translation done by [@Olafr9500](https://github.com/Olafr9500)
28 |
--------------------------------------------------------------------------------
/components/authors.js:
--------------------------------------------------------------------------------
1 | export default function Authors({ date, children, by = "by" }) {
2 | return (
3 |
4 | {date} {by} {children}
5 |
6 | );
7 | }
8 |
9 | export function Author({ name, link }) {
10 | return (
11 |
12 |
19 | {name}
20 |
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/components/blog-index.js:
--------------------------------------------------------------------------------
1 | import { getPagesUnderRoute } from "nextra/context";
2 | import filterRouteLocale from "nextra/filter-route-locale"
3 | import Link from "next/link";
4 | import { useRouter } from "next/router";
5 |
6 | export default function BlogIndex({ more = "Read more" }) {
7 | const { locale, defaultLocale } = useRouter();
8 | return filterRouteLocale(getPagesUnderRoute("/blog"), locale, defaultLocale).map((page) => {
9 | return (
10 |
11 |
12 |
17 | {page.meta?.title || page.frontMatter?.title || page.name}
18 |
19 |
20 |
21 | {page.frontMatter?.description}{" "}
22 |
23 |
27 | {more + " →"}
28 |
29 |
30 |
31 | {page.frontMatter?.date ? (
32 |
33 | {page.frontMatter.date}
34 |
35 | ) : null}
36 |
37 | );
38 | });
39 | }
40 |
--------------------------------------------------------------------------------
/components/diagrams/cache.js:
--------------------------------------------------------------------------------
1 | import useLocalesMap from "../use-locales-map";
2 | import { diagramCachePathsMap } from "../../translations/svgs";
3 |
4 | export const Cache = () => {
5 | const paths = useLocalesMap(diagramCachePathsMap);
6 |
7 | return (
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/components/diagrams/infinite.js:
--------------------------------------------------------------------------------
1 | import useLocalesMap from "../use-locales-map";
2 | import { diagramInfinitePathMap } from "../../translations/svgs";
3 |
4 | export const Infinite = () => {
5 | const path = useLocalesMap(diagramInfinitePathMap);
6 |
7 | return (
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
29 |
30 |
31 | );
32 | };
33 |
--------------------------------------------------------------------------------
/components/diagrams/pagination.js:
--------------------------------------------------------------------------------
1 | import useLocalesMap from "../use-locales-map";
2 | import { diagramPaginationPathsMap } from "../../translations/svgs";
3 |
4 | export const Pagination = () => {
5 | const paths = useLocalesMap(diagramPaginationPathsMap);
6 |
7 | return (
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
30 |
31 |
40 |
41 |
45 |
54 |
55 |
64 |
65 |
74 |
75 |
76 | );
77 | };
78 |
--------------------------------------------------------------------------------
/components/diagrams/welcome.js:
--------------------------------------------------------------------------------
1 | import useLocalesMap from "../use-locales-map";
2 | import { diagramWelcomePathMap } from "../../translations/svgs";
3 |
4 | export const Welcome = () => {
5 | const path = useLocalesMap(diagramWelcomePathMap);
6 |
7 | return (
8 |
9 |
10 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 | );
37 | };
38 |
--------------------------------------------------------------------------------
/components/features.js:
--------------------------------------------------------------------------------
1 | import { useId } from "react";
2 | import styles from "./features.module.css";
3 | import useLocalesMap from "./use-locales-map";
4 | import { featuresMap, titleMap } from "../translations/text";
5 |
6 | import BackendAgnosticIcon from "../components/icons/backend-agnostic";
7 | import LightweightIcon from "../components/icons/lightweight";
8 | import PaginationIcon from "../components/icons/pagination";
9 | import RealtimeIcon from "../components/icons/realtime";
10 | import RemoteLocalIcon from "../components/icons/remote-local";
11 | import RenderingStrategiesIcon from "../components/icons/rendering-strategies";
12 | import SuspenseIcon from "../components/icons/suspense";
13 | import TypeScriptIcon from "../components/icons/typescript";
14 |
15 | export function Feature({ text, icon }) {
16 | return (
17 |
18 | {icon}
19 |
{text}
20 |
21 | );
22 | }
23 |
24 | /** @type {{ key: string; icon: React.FC }[]} */
25 | const FEATURES_LIST = [
26 | { key: "lightweight", icon: },
27 | { key: "realtime", icon: },
28 | { key: "suspense", icon: },
29 | { key: "pagination", icon: },
30 | { key: "backendAgnostic", icon: },
31 | { key: "renderingStrategies", icon: },
32 | { key: "typescript", icon: },
33 | { key: "remoteLocal", icon: },
34 | ];
35 |
36 | export default function Features() {
37 | const keyId = useId();
38 | const title = useLocalesMap(titleMap);
39 | const features = useLocalesMap(featuresMap);
40 |
41 | return (
42 |
43 |
{title}
44 |
45 | {FEATURES_LIST.map(({ key, icon }) => (
46 |
47 | ))}
48 |
49 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/components/features.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: grid;
3 | grid-template-columns: 1fr 1fr 1fr 1fr;
4 | gap: 1rem 2rem;
5 | margin: 2.5rem 0 2rem;
6 | }
7 | .feature {
8 | align-items: center;
9 | display: inline-flex;
10 | }
11 | .feature h4 {
12 | margin: 0 0 0 0.5rem;
13 | font-weight: 700;
14 | font-size: 1.1rem;
15 | white-space: nowrap;
16 | }
17 | @media (max-width: 860px) {
18 | .features {
19 | gap: 1rem 0.5rem;
20 | }
21 | .feature {
22 | padding-left: 0;
23 | justify-content: center;
24 | }
25 | .feature svg {
26 | width: 20px;
27 | }
28 | .feature h4 {
29 | font-size: 0.9rem;
30 | }
31 | }
32 | @media (max-width: 660px) {
33 | .features {
34 | grid-template-columns: 1fr 1fr;
35 | }
36 | }
37 | @media (max-width: 370px) {
38 | .feature h4 {
39 | font-size: 0.8rem;
40 | }
41 | .feature svg {
42 | width: 16px;
43 | stroke-width: 2.5px;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/components/icons/backend-agnostic.js:
--------------------------------------------------------------------------------
1 | export default function BackendAgnosticIcon() {
2 | return (
3 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/components/icons/lightweight.js:
--------------------------------------------------------------------------------
1 | export default function LightweightIcon() {
2 | return (
3 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/icons/pagination.js:
--------------------------------------------------------------------------------
1 | export default function PaginationIcon() {
2 | return (
3 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/icons/realtime.js:
--------------------------------------------------------------------------------
1 | export default function RealtimeIcon() {
2 | return (
3 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/components/icons/remote-local.js:
--------------------------------------------------------------------------------
1 | export default function RemoteLocalIcon() {
2 | return (
3 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/icons/rendering-strategies.js:
--------------------------------------------------------------------------------
1 | export default function RenderingStrategiesIcon() {
2 | return (
3 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/components/icons/suspense.js:
--------------------------------------------------------------------------------
1 | export default function SuspenseIcon() {
2 | return (
3 |
13 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/icons/typescript.js:
--------------------------------------------------------------------------------
1 | export default function TypescriptIcon() {
2 | return (
3 |
14 |
15 |
16 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/components/logo.js:
--------------------------------------------------------------------------------
1 | export default function Logo({ height }) {
2 | return (
3 |
4 |
8 |
9 | );
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/components/use-locales-map.js:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 |
3 | /**
4 | * @typedef {"en-US"} DefaultLocale
5 | * @typedef {DefaultLocale | "zh-CN" | "es-ES" | "fr-FR" | "pt-BR" | "ja" | "ko" | "ru"} Locale
6 | * @typedef {{locale?: Locale | undefined; locales?: Locale[] | undefined; defaultLocale?: DefaultLocale | undefined}} TypedRouter
7 | * @typedef {Omit & TypedRouter} NextRouter
8 | * @template T
9 | * @type {(localesMap: Record) => T}
10 | */
11 | export default function useLocalesMap(localesMap) {
12 | /** @type {NextRouter} */
13 | const router = useRouter();
14 | const { locale, defaultLocale } = router;
15 | if (!localesMap) {
16 | throw new Error("Pass a locales map as argument to useLocalesMap");
17 | }
18 |
19 | if (!isObject(localesMap)) {
20 | throw new Error("Locales map must be an object");
21 | }
22 |
23 | if (!localesMap.hasOwnProperty(defaultLocale)) {
24 | throw new Error(
25 | `Locales map must contain default locale "${defaultLocale}"`
26 | );
27 | }
28 |
29 | if (
30 | localesMap.hasOwnProperty(locale) &&
31 | typeof localesMap[locale] !== typeof localesMap[defaultLocale]
32 | ) {
33 | throw new Error(
34 | `Invalid locales map: Shape of "${locale}" must be the same as "${defaultLocale}"`
35 | );
36 | }
37 |
38 | if (["string", "number", "symbol"].includes(typeof localesMap[defaultLocale])) {
39 | return localesMap[locale] || localesMap[defaultLocale];
40 | }
41 |
42 | const target = JSON.parse(JSON.stringify(localesMap[defaultLocale]));
43 | return mergeDeep(target, localesMap[locale]);
44 | }
45 |
46 | /**
47 | * Simple object check.
48 | * @param {any} item
49 | * @returns {boolean}
50 | */
51 | function isObject(item) {
52 | return item && typeof item === "object" && !Array.isArray(item);
53 | }
54 |
55 | /**
56 | * Deep merge two objects.
57 | * @template T
58 | * @param {Record} target
59 | * @param {Record} sources
60 | * @returns {Record}
61 | */
62 | function mergeDeep(target, ...sources) {
63 | if (!sources.length) return target;
64 | const source = sources.shift();
65 |
66 | if (isObject(target) && isObject(source)) {
67 | for (const key in source) {
68 | if (isObject(source[key])) {
69 | if (!target[key]) Object.assign(target, { [key]: {} });
70 | mergeDeep(target[key], source[key]);
71 | } else {
72 | Object.assign(target, { [key]: source[key] });
73 | }
74 | }
75 | }
76 |
77 | return mergeDeep(target, ...sources);
78 | }
79 |
--------------------------------------------------------------------------------
/components/vercel.js:
--------------------------------------------------------------------------------
1 | export default function Vercel({ height = 20 }) {
2 | return (
3 |
4 |
8 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/components/video.js:
--------------------------------------------------------------------------------
1 | import "intersection-observer";
2 | import { useCallback, useEffect, useRef } from "react";
3 | import { useInView } from "react-intersection-observer";
4 |
5 |
6 | export default function Video({ src, caption, ratio, className = "" }) {
7 | const [inViewRef, inView] = useInView({
8 | threshold: 1,
9 | });
10 | const videoRef = useRef();
11 |
12 | const setRefs = useCallback(
13 | (node) => {
14 | // Ref's from useRef needs to have the node assigned to `current`
15 | videoRef.current = node;
16 | // Callback refs, like the one from `useInView`, is a function that takes the node as an argument
17 | inViewRef(node);
18 |
19 | if (node) {
20 | node.addEventListener("click", function () {
21 | if (this.paused) {
22 | this.play();
23 | } else {
24 | this.pause();
25 | }
26 | });
27 | }
28 | },
29 | [inViewRef]
30 | );
31 |
32 | useEffect(() => {
33 | if (!videoRef || !videoRef.current) {
34 | return;
35 | }
36 |
37 | if (inView) {
38 | videoRef.current.play();
39 | } else {
40 | videoRef.current.pause();
41 | }
42 | }, [inView]);
43 |
44 | return (
45 |
49 |
50 |
58 |
59 |
60 | {caption && (
61 |
64 | {caption}
65 |
66 | )}
67 |
68 | );
69 | };
70 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "."
4 | }
5 | }
--------------------------------------------------------------------------------
/middleware.js:
--------------------------------------------------------------------------------
1 | export { locales as middleware } from "nextra/locales";
2 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const withNextra = require("nextra")({
2 | theme: "nextra-theme-docs",
3 | themeConfig: "./theme.config.js",
4 | staticImage: true,
5 | flexsearch: {
6 | codeblocks: false,
7 | },
8 | defaultShowCopyCode: true,
9 | });
10 |
11 | module.exports = withNextra({
12 | i18n: {
13 | locales: ["en-US", "zh-CN", "es-ES", "fr-FR", "pt-BR", "ja", "ko", "ru"],
14 | defaultLocale: "en-US",
15 | },
16 | redirects: () => {
17 | return [
18 | {
19 | source: "/docs",
20 | destination: "/docs/getting-started",
21 | statusCode: 301,
22 | },
23 | {
24 | source: "/advanced/performance",
25 | destination: "/docs/advanced/performance",
26 | statusCode: 301,
27 | },
28 | {
29 | source: "/advanced/cache",
30 | destination: "/docs/advanced/cache",
31 | statusCode: 301,
32 | },
33 | {
34 | source: "/docs/cache",
35 | destination: "/docs/advanced/cache",
36 | statusCode: 301,
37 | },
38 | {
39 | source: "/docs/options",
40 | destination: "/docs/api",
41 | statusCode: 301,
42 | },
43 | {
44 | source: "/change-log",
45 | destination: "/docs/change-log",
46 | statusCode: 301,
47 | },
48 | {
49 | source: "/blog/swr-1",
50 | destination: "/blog/swr-v1",
51 | statusCode: 301,
52 | },
53 | {
54 | source: "/docs",
55 | destination: "/docs/getting-started",
56 | statusCode: 302,
57 | },
58 | {
59 | source: "/examples",
60 | destination: "/examples/basic",
61 | statusCode: 302,
62 | },
63 | ];
64 | },
65 | reactStrictMode: true,
66 | });
67 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "swr-site",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "next",
8 | "debug": "NODE_OPTIONS='--inspect' next",
9 | "start": "next start",
10 | "build": "next build"
11 | },
12 | "author": "Shu Ding",
13 | "license": "Apache-2.0",
14 | "dependencies": {
15 | "@vercel/analytics": "^0.1.11",
16 | "focus-visible": "^5.2.0",
17 | "intersection-observer": "^0.12.2",
18 | "next": "14.2.24",
19 | "nextra": "^2.13.4",
20 | "nextra-theme-docs": "^2.4.2",
21 | "react": "^18.3.1",
22 | "react-dom": "^18.3.1",
23 | "react-intersection-observer": "^9.4.3"
24 | },
25 | "devDependencies": {
26 | "autoprefixer": "^10.4.14",
27 | "postcss": "^8.4.21",
28 | "tailwindcss": "^3.2.7"
29 | },
30 | "prettier": {
31 | "embeddedLanguageFormatting": "off",
32 | "htmlWhitespaceSensitivity": "strict"
33 | },
34 | "packageManager": "pnpm@9.15.4"
35 | }
36 |
--------------------------------------------------------------------------------
/pages/_app.mdx:
--------------------------------------------------------------------------------
1 | import "../styles.css";
2 | import { Analytics } from "@vercel/analytics/react";
3 |
4 | export default function Nextra({ Component, pageProps }) {
5 | return (
6 | <>
7 |
8 |
9 | >
10 | );
11 | }
12 |
--------------------------------------------------------------------------------
/pages/_document.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Document, { Html, Head, Main, NextScript } from 'next/document'
3 | import { SkipNavLink } from "nextra-theme-docs";
4 |
5 | class MyDocument extends Document {
6 | render() {
7 | return (
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 | }
19 |
20 | export default MyDocument
21 |
--------------------------------------------------------------------------------
/pages/_meta.en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Introduction",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "Docs",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "Examples",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "Blog",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.es-ES.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Introducción",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "Docs",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "Ejemplos",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "Blog",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.fr-FR.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Introduction",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "Docs",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "Exemples",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "Blog",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "前書き",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "ドキュメント",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "例",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "ブログ",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "소개",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "문서",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "예시",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "블로그",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.pt-BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Introdução",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "Documentação",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "Exemplos",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "Blog",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "Введение",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "Документация",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "Примеры",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "Блог",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_meta.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "index": {
3 | "title": "简介",
4 | "type": "page",
5 | "display": "hidden"
6 | },
7 | "docs": {
8 | "title": "文档",
9 | "type": "page"
10 | },
11 | "examples": {
12 | "title": "示例",
13 | "type": "page"
14 | },
15 | "blog": {
16 | "title": "博客",
17 | "type": "page",
18 | "theme": {
19 | "sidebar": false
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/pages/blog.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR Blog
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR Blog
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR Blog
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR Blog
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 블로그
3 | searchable: false
4 | ---
5 |
6 | SWR 블로그
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR Blog
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Блог
3 | searchable: false
4 | ---
5 |
6 | Блог SWR
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Blog
3 | searchable: false
4 | ---
5 |
6 | SWR 博客
7 |
8 | import BlogIndex from '../components/blog-index'
9 |
10 |
11 |
--------------------------------------------------------------------------------
/pages/blog/_meta.en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "Announcing SWR 2.0",
3 | "swr-v1": "Announcing SWR 1.0"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.es-ES.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "Announcing SWR 2.0",
3 | "swr-v1": "Announcing SWR 1.0"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.fr-FR.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "Annonce SWR 2.0",
3 | "swr-v1": "Annonce SWR 1.0"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "SWR 2.0 の発表",
3 | "swr-v1": "SWR 1.0 の発表"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "SWR 2.0 발표",
3 | "swr-v1": "SWR 1.0 알림"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.pt-BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "Anunciando SWR 2.0",
3 | "swr-v1": "Anunciando SWR 1.0"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "Представляем SWR 2.0",
3 | "swr-v1": "Представляем SWR 1.0"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/blog/_meta.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "swr-v2": "SWR 2.0 发布",
3 | "swr-v1": "SWR 1.0 发布"
4 | }
5 |
--------------------------------------------------------------------------------
/pages/docs/_meta.en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "Getting Started",
3 | "api": "API",
4 | "global-configuration": "Global Configuration",
5 | "data-fetching": "Data Fetching",
6 | "revalidation": "Auto Revalidation",
7 | "arguments": "Arguments",
8 | "mutation": "Mutation & Revalidation",
9 | "error-handling": "Error Handling",
10 | "conditional-fetching": "Conditional Data Fetching",
11 | "pagination": "Pagination",
12 | "subscription": "Subscription",
13 | "prefetching": "Prefetching",
14 | "with-nextjs": "Next.js SSG and SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "Suspense",
17 | "middleware": "Middleware",
18 | "advanced": "Advanced",
19 | "change-log": {
20 | "title": "Change Log",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.es-ES.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "Comienza",
3 | "api": "API",
4 | "global-configuration": "Configuración Global",
5 | "data-fetching": "Obtención De Datos",
6 | "error-handling": "Gestión De Errores",
7 | "revalidation": "Revalidación Automática",
8 | "conditional-fetching": "Obtención De Datos Condicional",
9 | "arguments": "Argumentos",
10 | "mutation": "Mutación",
11 | "pagination": "Paginación",
12 | "subscription": "Subscription",
13 | "prefetching": "Prefetching",
14 | "with-nextjs": "Next.js SSG and SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "Suspense",
17 | "middleware": "Middleware",
18 | "advanced": "Avanzado",
19 | "change-log": {
20 | "title": "Registro de cambios",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.fr-FR.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "Démarrage rapide",
3 | "api": "API",
4 | "global-configuration": "Configuration Globale",
5 | "data-fetching": "Récupération des données",
6 | "revalidation": "Auto Revalidation",
7 | "arguments": "Arguments",
8 | "mutation": "Mutation & Revalidation",
9 | "error-handling": "Gestion des erreurs",
10 | "conditional-fetching": "Récupération de données Conditionnelle",
11 | "pagination": "Pagination",
12 | "subscription": "Abonnement",
13 | "prefetching": "Préchargement des données",
14 | "with-nextjs": "Utilisation avec Next.js",
15 | "typescript": "TypeScript",
16 | "suspense": "Suspense",
17 | "middleware": "Middleware",
18 | "advanced": "Avancé",
19 | "change-log": {
20 | "title": "Change Log",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "はじめに",
3 | "api": "API",
4 | "global-configuration": "グローバルな設定",
5 | "data-fetching": "データの取得",
6 | "error-handling": "エラーハンドリング",
7 | "revalidation": "自動再検証",
8 | "conditional-fetching": "条件付きフェッチ",
9 | "arguments": "引数",
10 | "mutation": "ミューテーションと再検証",
11 | "pagination": "ページネーション",
12 | "subscription": "サブスクリプション",
13 | "prefetching": "プリフェッチ",
14 | "with-nextjs": "Next.js の SSG と SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "サスペンス",
17 | "middleware": "ミドルウェア",
18 | "advanced": "高度な使い方",
19 | "change-log": {
20 | "title": "変更履歴",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "시작하기",
3 | "api": "API",
4 | "global-configuration": "전역 설정",
5 | "data-fetching": "데이터 가져오기",
6 | "error-handling": "에러 처리",
7 | "revalidation": "자동 갱신",
8 | "conditional-fetching": "조건부 데이터 가져오기",
9 | "arguments": "인자",
10 | "mutation": "뮤테이션",
11 | "pagination": "페이지네이션",
12 | "subscription": "구독",
13 | "prefetching": "프리패칭",
14 | "with-nextjs": "Next.js SSG 및 SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "서스펜스",
17 | "middleware": "미들웨어",
18 | "advanced": "고급",
19 | "change-log": {
20 | "title": "변경 로그",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.pt-BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "Comece a Usar",
3 | "api": "API",
4 | "global-configuration": "Configuração Global",
5 | "data-fetching": "Data Fetching",
6 | "error-handling": "Manipulação de Erros",
7 | "revalidation": "Revalidação",
8 | "conditional-fetching": "Data Fetching Condicional",
9 | "arguments": "Argumentos",
10 | "mutation": "Mutação",
11 | "pagination": "Paginação",
12 | "subscription": "Inscrição",
13 | "prefetching": "Pre-obtendo Dados",
14 | "with-nextjs": "SSG e SSR com Next.js",
15 | "typescript": "TypeScript",
16 | "suspense": "Suspense",
17 | "middleware": "Middleware",
18 | "advanced": "Avançado",
19 | "change-log": {
20 | "title": "Change Log",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
--------------------------------------------------------------------------------
/pages/docs/_meta.ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "Начало работы",
3 | "api": "API",
4 | "global-configuration": "Глобальная конфигурация",
5 | "data-fetching": "Выборка данных",
6 | "error-handling": "Обработка ошибок",
7 | "revalidation": "Авто-ревалидация",
8 | "conditional-fetching": "Условная выборка данных",
9 | "arguments": "Аргументы",
10 | "mutation": "Мутация",
11 | "pagination": "Пагинация",
12 | "subscription": "Подписка",
13 | "prefetching": "Пред-выборка",
14 | "with-nextjs": "Next.js SSG и SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "Задержка (Suspense)",
17 | "middleware": "Промежуточное ПО (Middleware)",
18 | "advanced": "Продвинутые",
19 | "change-log": {
20 | "title": "Журнал изменений",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pages/docs/_meta.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "getting-started": "入门",
3 | "api": "API",
4 | "global-configuration": "全局配置",
5 | "data-fetching": "数据请求",
6 | "error-handling": "错误处理",
7 | "revalidation": "自动重新请求",
8 | "conditional-fetching": "条件数据请求",
9 | "arguments": "传入参数",
10 | "mutation": "数据更改",
11 | "pagination": "分页",
12 | "subscription": "订阅",
13 | "prefetching": "预请求",
14 | "with-nextjs": "Next.js SSG 和 SSR",
15 | "typescript": "TypeScript",
16 | "suspense": "Suspense",
17 | "middleware": "中间件",
18 | "advanced": "高级",
19 | "change-log": {
20 | "title": "更新日志",
21 | "href": "https://github.com/vercel/swr/releases",
22 | "newWindow": true
23 | }
24 | }
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Understanding SWR",
3 | "cache": "Cache",
4 | "performance": "Performance",
5 | "react-native": "React Native",
6 | "devtools": "Developer Tools"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.es-ES.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Understanding SWR",
3 | "cache": "Cache",
4 | "performance": "Rendimiento",
5 | "react-native": "React Native",
6 | "devtools": "Developer Tools"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.fr-FR.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Compréhension SWR",
3 | "cache": "Cache",
4 | "performance": "Performance",
5 | "react-native": "React Native",
6 | "devtools": "Outils Développeur"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "SWR を理解する",
3 | "cache": "キャッシュ",
4 | "performance": "パフォーマンス",
5 | "react-native": "React Native",
6 | "devtools": "開発者ツール"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Understanding SWR",
3 | "cache": "캐시",
4 | "performance": "성능",
5 | "react-native": "React Native",
6 | "devtools": "Developer Tools"
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.pt-BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Entendendo o SWR",
3 | "cache": "Cache",
4 | "performance": "Desempenho",
5 | "react-native": "React Native",
6 | "devtools": "Ferramentas de Desenvolvedor"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "Понимание SWR",
3 | "cache": "Кеш",
4 | "performance": "Производительность",
5 | "react-native": "React Native",
6 | "devtools": "Инструменты разработчика"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/_meta.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "understanding": "理解 SWR",
3 | "cache": "缓存",
4 | "performance": "性能",
5 | "react-native": "React Native",
6 | "devtools": "Developer Tools"
7 | }
8 |
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.en-US.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # DevTools
4 |
5 |
6 | SWRDevTools is not an official project of Vercel.
7 |
8 |
9 | [SWRDevTools](https://swr-devtools.vercel.app/) is a developer tool for SWR, which helps to debug your SWR cache and fetchers.
10 |
11 |
12 | You can install SWR DevTools from the extension pages and use it with zero settings!
13 |
14 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
15 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
16 |
17 | After installing it, the SWR devtool panel will appear on browsers' developer tools.
18 |
19 | Checkout more information on the [website](https://swr-devtools.vercel.app/) and the [repository](https://github.com/koba04/swr-devtools)
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.es-ES.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # DevTools
4 |
5 |
6 |
7 | SWRDevTools is not an official project of Vercel.
8 |
9 |
10 | [SWRDevTools](https://swr-devtools.vercel.app/) is a developer tool for SWR, which helps to debug your SWR cache and fetchers.
11 |
12 |
13 | You can install SWR DevTools from the extension pages and use it with zero settings!
14 |
15 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
16 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
17 |
18 | After installing it, the SWR devtool panel will appear on browsers' developer tools.
19 |
20 | Checkout more information on the [website](https://swr-devtools.vercel.app/) and the [repository](https://github.com/koba04/swr-devtools)
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Outils Développeur
4 |
5 |
6 | SWRDevTools n'est pas un projet officiel de Vercel.
7 |
8 |
9 | [SWRDevTools](https://swr-devtools.vercel.app/) est un outil de développement pour SWR, qui aide à déboguer votre cache SWR et vos fetchers.
10 |
11 | Vous pouvez installer SWRDevTools depuis les pages d'extension et l'utiliser sans aucun paramètre !
12 |
13 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
14 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
15 |
16 | Après l'avoir installé, le panneau d'outils de développement SWR apparaîtra dans les outils de développement des navigateurs.
17 |
18 | Pour plus d'information, rendez-vous sur le [site](https://swr-devtools.vercel.app/) et le [dépôt](https://github.com/koba04/swr-devtools)
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.ja.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # 開発者ツール
4 |
5 |
6 |
7 | SWRDevTools は Vercel 公式プロジェクトではありません。
8 |
9 |
10 | [SWRDevTools](https://swr-devtools.vercel.app/) は SWR のための開発者ツールで、SWR のキャッシュやフェッチの状態のデバッグに役に立ちます。
11 |
12 | SWR DevTools はブラウザ拡張のページからインストールするだけで、追加の設定なしに使うことができます。
13 |
14 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
15 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
16 |
17 | インストール後、SWR 用のパネルがブラウザの開発者ツールに追加されます。
18 |
19 | 機能については SWRDevTools の [ウェブサイト](https://swr-devtools.vercel.app/) と [リポジトリ](https://github.com/koba04/swr-devtools) を確認してください。
20 |
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.ko.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # 개발자 도구
4 |
5 |
6 | SWRDevTools는 Vercel의 공식 프로젝트가 아닙니다.
7 |
8 |
9 | [SWRDevTools](https://swr-devtools.vercel.app/)는 SWR 캐시 및 페처를 디버깅하는 데 도움이 되는 SWR용 개발자 도구입니다.
10 |
11 | 확장 페이지에서 SWR 개발자 도구를 설치하여 아무런 설정 없이 사용할 수 있습니다!
12 |
13 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
14 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
15 |
16 | After installing it, the SWR devtool panel will appear on browsers' developer tools.
17 | 설치 후 브라우저의 개발자 도구에 SWR 개발자 도구 패널이 나타납니다.
18 |
19 | [웹사이트](https://swr-devtools.vercel.app/) 및 [리포지터리](https://github.com/koba04/swr-devtools)에서 자세한 정보를 확인하세요/
20 |
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # DevTools
4 |
5 |
6 | SWRDevTools não é um projeto oficial da Vercel.
7 |
8 |
9 | [SWRDevTools](https://swr-devtools.vercel.app/) é uma ferramenta de desenvolvimento para SWR, que ajuda a depurar seu cache e fetchers do SWR.
10 |
11 | Você pode instalar o SWR DevTools pelas páginas de extensão e usar com zero configuração!
12 |
13 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
14 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
15 |
16 | Após instalar, o painel do SWR DevTools irá aparecer nas ferramentas de desenvolvedor dos navegadores.
17 |
18 | Confira mais informações no [website](https://swr-devtools.vercel.app/) e no [repositório](https://github.com/koba04/swr-devtools).
19 |
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.ru.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Инструменты разработчика
4 |
5 |
6 |
7 | SWRDevTools не является официальным проектом Vercel.
8 |
9 |
10 | [SWRDevTools](https://swr-devtools.vercel.app/) — это инструмент разработчика для SWR, который помогает отлаживать кеш и fetcher-ы SWR.
11 |
12 | Вы можете установить SWR DevTools со страниц расширения и использовать его с нулевыми настройками!
13 |
14 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
15 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
16 |
17 | После его установки в инструментах разработчика браузеров появится панель SWR devtool.
18 |
19 | Ознакомьтесь с дополнительной информацией на [веб-сайте](https://swr-devtools.vercel.app/) и в [репозитории](https://github.com/koba04/swr-devtools).
20 |
--------------------------------------------------------------------------------
/pages/docs/advanced/devtools.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # DevTools
4 |
5 |
6 | SWRDevTools不是Vercel官方项目。
7 |
8 |
9 | [SWRDevTools](https://swr-devtools.vercel.app/) 是为SWR量身定制的开发工具,它可以帮助你调试SWR的缓存和请求。
10 |
11 |
12 | 你可以通过浏览器扩展页面安装SWR DevTools,无需任何配置就可以使用它。
13 |
14 | - Chrome: https://chrome.google.com/webstore/detail/swr-devtools/liidbicegefhheghhjbomajjaehnjned
15 | - Firefox: https://addons.mozilla.org/en-US/firefox/addon/swr-devtools/
16 |
17 | 安装之后,可以在浏览器的开发人员工具中看到SWR面板。
18 |
19 | 更多信息请访问 [SWR官网](https://swr-devtools.vercel.app/) 和 [GitHub仓库](https://github.com/koba04/swr-devtools)
--------------------------------------------------------------------------------
/pages/docs/advanced/performance.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | # 性能
2 |
3 | SWR 在各种 web 应用中提供了关键功能,因此 **性能** 是重中之重。
4 |
5 | SWR 内置的 **缓存** 和 **[重复数据删除](#重复数据删除)** 会跳过不必要的网络请求,但 `useSWR` hook 本身的性能仍然很重要。在一个复杂的应用中,单个页面渲染可能会调用数百次 `useSWR`。
6 |
7 | SWR 确保你的应用具有:
8 | - _没有不必要的请求_
9 | - _没有不必要的重新渲染_
10 | - _没有不必要的代码导入_
11 |
12 | 而无需你更改任何代码。
13 |
14 | ## 重复数据删除 [#deduplication]
15 |
16 | 在应用中重用 SWR hooks 非常常见。例如,一个应用渲染 5 次当前用户的头像:
17 |
18 | ```jsx
19 | function useUser () {
20 | return useSWR('/api/user', fetcher)
21 | }
22 |
23 | function Avatar () {
24 | const { data, error } = useUser()
25 |
26 | if (error) return
27 | if (!data) return
28 |
29 | return
30 | }
31 |
32 | function App () {
33 | return <>
34 |
35 |
36 |
37 |
38 |
39 | >
40 | }
41 | ```
42 |
43 | 每个 `` 组件内部都有一个 `useSWR` hook。由于它们具有相同的 SWR key,并且几乎同时渲染,因此 **只会发送 1 个网络请求**。
44 |
45 | 你可以在任何地方重用数据 hooks(比如上面示例中的 `useUser`),而不用担心性能或重复请求。
46 |
47 | 还有一个 [`dedupingInterval` 选项](/docs/api) 用于覆盖默认的重复数据删除间隔。
48 |
49 | ## 深度比较 [#deep-comparison]
50 |
51 | SWR 默认 **深度比较** 数据更改。如果 `data` 值没有改变,则不会触发重新渲染。
52 |
53 | 如果你还想更改的话,可以通过 [`compare` 选项](/docs/api) 自定义比较函数。比如,某些 API 响应返回一个服务器时间戳,你可能想从数据 diff 中排除它。
54 |
55 | ## 依赖收集 [#dependency-collection]
56 |
57 | `useSWR` 返回 4 个 **有状态的** 值:`data`、`error`、`isLoading`和 `isValidating`,每个都可以独立更新。例如,如果我们在一个完整的数据请求生命周期中打印这些值,则将如下所示:
58 |
59 | ```jsx
60 | function App () {
61 | const { data, error, isLoading, isValidating } = useSWR('/api', fetcher)
62 | console.log(data, error, isLoading, isValidating)
63 | return null
64 | }
65 | ```
66 |
67 | 在最坏的情况下(第一个请求失败,然后重试成功),你将看到 4 行日志:
68 |
69 | ```js
70 | // console.log(data, error, isLoading, isValidating)
71 | undefined undefined true true // => 开始 fetching
72 | undefined Error false false // => 结束 fetching,出现错误
73 | undefined Error true true // => 开始重试
74 | Data undefined false false // => 重试结束,得到数据
75 | ```
76 |
77 | 状态的改变是有道理的。但这也意味着组件 **渲染了 4 次**。
78 |
79 | 如果我们将组件更改为只使用 `data`:
80 |
81 | ```jsx
82 | function App () {
83 | const { data } = useSWR('/api', fetcher)
84 | console.log(data)
85 | return null
86 | }
87 | ```
88 |
89 | 神奇的事情发生了 - 现在只有 **2 次重新渲染**:
90 |
91 | ```js
92 | // console.log(data)
93 | undefined // => hydration / 初始渲染
94 | Data // => 重试结束,得到数据
95 | ```
96 |
97 | 内部发生了完全相同的过程,第一个请求出现了错误,然后我们重试得到了数据。但是,**SWR 只更新了组件使用的状态**,即:`data`。
98 |
99 | 如果你不是总使用这3种状态,那么你已经从这个特性中获益了。在 [Vercel](https://vercel.com) 的实际应用中,这个优化减少了约 60% 的重新渲染。
100 |
101 | ## Tree Shaking [#tree-shaking]
102 |
103 | SWR 满足 [tree-shakeable](https://webpack.js.org/guides/tree-shaking) 且没有副作用。这意味着如果你只导入核心的 `useSWR` API,像 `useSWRInfinite` 这样的未使用的 API 将不会绑定到你的应用中。
104 |
--------------------------------------------------------------------------------
/pages/docs/advanced/react-native.ja.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # React Native
4 |
5 |
6 | このカスタマイズを体験するには、最新バージョン( ≥ 1.0.0 )にアップグレードしてください。
7 |
8 |
9 | ブラウザ内で実行されている React とは異なり、React Native の使用体験は大きく異なります。たとえば、“タブフォーカス”はなく、バックグラウンドからアプリの切り替えは“フォーカス”とみなされます。
10 | これらの動作をカスタマイズするには、デフォルトの `focus` と `online` のイベントリスナーを React Native のアプリの状態検出や、その他のネイティブ移植 API に置き換えて使用するように SWR を構成します。
11 |
12 | ## 例 [#example]
13 |
14 | ### グローバル設定 [#global-setup]
15 |
16 | アプリを `SWRConfig` でラップし、すべての構成を事前に設定できます。
17 |
18 | ```jsx
19 |
24 |
25 |
26 | ```
27 |
28 | ### `focus` と `reconnect` イベントのカスタマイズ [#customize-focus-and-reconnect-events]
29 |
30 | `isOnline` 、 `isVisible` 、 `initFocus` 、 `initReconnect` など、いくつかの設定を行う必要があります。
31 |
32 | `isOnline` と `isVisible` は、アプリケーションが"アクティブ"であるかどうかを判断するための真偽値を返す関数です。デフォルトでは、これらの条件が満たされてない場合、 SWR は再検証を中止します。
33 |
34 | `initFocus` と `initReconnect` を使用する場合は、[カスタムキャッシュプロバイダー](/docs/advanced/cache)も設定する必要があります。空の `Map()` 、または任意のストレージを使用できます。
35 |
36 | ```jsx
37 | new Map(),
40 | isOnline() {
41 | /* ネットワーク状態の検出器をカスタマイズ */
42 | return true
43 | },
44 | isVisible() {
45 | /* 視認状態の検出器をカスタマイズ */
46 | return true
47 | },
48 | initFocus(callback) {
49 | /* リスナーをステートプロバイダーに登録 */
50 | },
51 | initReconnect(callback) {
52 | /* リスナーをステートプロバイダーに登録 */
53 | }
54 | }}
55 | >
56 |
57 |
58 | ```
59 |
60 | ここでは、 `initFocus` を例に説明します:
61 |
62 | ```jsx
63 | import { AppState } from 'react-native'
64 |
65 | // ...
66 |
67 | new Map(),
70 | isVisible: () => { return true },
71 | initFocus(callback) {
72 | let appState = AppState.currentState
73 |
74 | const onAppStateChange = (nextAppState) => {
75 | /* バックグラウンドモードまたは非アクティブモードからアクティブモードに再開する場合 */
76 | if (appState.match(/inactive|background/) && nextAppState === 'active') {
77 | callback()
78 | }
79 | appState = nextAppState
80 | }
81 |
82 | // アプリの状態変更を監視する
83 | const subscription = AppState.addEventListener('change', onAppStateChange)
84 |
85 | return () => {
86 | subscription.remove()
87 | }
88 | }
89 | }}
90 | >
91 |
92 |
93 | ```
94 |
95 | `initReconnect` の場合、ネットワーク状態を監視するには [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) などのサードパーティ製のライブラリが必要です。実装は上記の例と同様です: `callback` 関数を受け取り、ネットワークがオフラインから復帰したときに実行するため、 SWR は再検証を開始してデータを最新の状態に保つことができます。
--------------------------------------------------------------------------------
/pages/docs/advanced/react-native.ko.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # React Native
4 |
5 |
6 | 이 커스터마이재이션을 경험하시려면 최신 버전(≥ 1.0.0)으로 업그레이드하세요.
7 |
8 |
9 | 브라우저 내에서 실행되는 React와 달리, React Native는 사용 환경이 매우 다릅니다. 예를 들면, "tab focus"가 없습니다. 대신에 백그라운드에서 앱으로 전환하는 것은 "focus"로 간주합니다.
10 | 이러한 동작을 커스터마이징 하려면 기본 브라우저 `focus`와 `online` 이벤트 리스너를 React Native의 앱 상태 감지와 네이티브에서 이식된 다른 API로 교체하고, SWR이 사용하도록 설정해야 합니다.
11 |
12 |
13 | ## 예시 [#example]
14 |
15 |
16 | ### 전역 설치 [#global-setup]
17 |
18 | `SWRConfig` 아래의 앱을 감싸고 모든 설정을 미리 구성할 수 있습니다.
19 |
20 | ```jsx
21 |
26 |
27 |
28 | ```
29 |
30 | ### `focus` 및 `reconnect` 이벤트 커스터마이징 하기 [#customize-focus-and-reconnect-events]
31 |
32 | 신경 써야 할 설정은 `isOnline`, `isVisible`, `initFocus` 및 `initReconnect`로 많지 않습니다.
33 |
34 | `isOnline`과 `isVisible`은 boolean을 반환하는 함수로, 애플리케이션이 "active"인지 여부를 확인합니다. 기본적으로 SWR은 이러한 조건들이 충족되지 않으면 재검증을 하지 않습니다.
35 |
36 | `initFocus`와 `initReconnect`을 사용할 때, [커스텀 캐시 공급자](/docs/advanced/cache)도 설정해야 합니다. 빈 `Map()` 또는 원하는 저장소를 사용하면 됩니다.
37 |
38 | ```jsx
39 | new Map(),
42 | isOnline() {
43 | /* 네트워크 상태 감지자 커스터마이징 */
44 | return true
45 | },
46 | isVisible() {
47 | /* visibility 상태 감지자 커스터마이징 */
48 | return true
49 | },
50 | initFocus(callback) {
51 | /* 상태 공급자에 리스너 등록 */
52 | },
53 | initReconnect(callback) {
54 | /* 상태 공급자에 리스터 등록 */
55 | }
56 | }}
57 | >
58 |
59 |
60 | ```
61 |
62 | `initFocus`를 예로 들어보겠습니다.
63 |
64 |
65 | ```jsx
66 | import { AppState } from 'react-native'
67 |
68 | // ...
69 |
70 | new Map(),
73 | isVisible: () => { return true },
74 | initFocus(callback) {
75 | let appState = AppState.currentState
76 |
77 | const onAppStateChange = (nextAppState) => {
78 | /* 백그라운드 또는 비활성 모드에서 활성 모드로 다시 시작하는 경우 */
79 | if (appState.match(/inactive|background/) && nextAppState === 'active') {
80 | callback()
81 | }
82 | appState = nextAppState
83 | }
84 |
85 | // 앱 상태 변경 이벤트 구독
86 | const subscription = AppState.addEventListener('change', onAppStateChange)
87 |
88 | return () => {
89 | subscription.remove()
90 | }
91 | }
92 | }}
93 | >
94 |
95 |
96 | ```
97 |
98 | `initReconnect`의 경우, 네트워크 상태를 구독하려면 [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo)와 같은 제3자 라이브러리가 필요합니다. 구현은 위 예시와 유사합니다. `callback` 함수를 받고 네트워크가 오프라인으로부터 복구될 때 이를 실행하여 SWR이 재검증을 시작하고 데이터를 최신으로 유지할 수 있습니다.
99 |
--------------------------------------------------------------------------------
/pages/docs/advanced/react-native.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # React Native
4 |
5 |
6 | 升级到最新版本(≥ 1.0.0)来体验该定制。
7 |
8 |
9 | 与在浏览器中运行的 React 不同,React Native 有着非常不同的使用体验。比如没有“标签聚焦”,而从后台切换到 app 则被视为“聚焦”。要想自定义这些行为,你可以使用 React Native 的 app 状态检测和其他原生移植 API 替换默认的 `focus` 和 `online`,并配置 SWR 来使用。
10 |
11 | ## 示例 [#example]
12 |
13 | ### 全局设置 [#global-setup]
14 |
15 | 你可以将 app 包装在 `SWRConfig` 下并预设置所有配置
16 |
17 | ```jsx
18 |
23 |
24 |
25 | ```
26 |
27 | ### 自定义 `focus` 和 `reconnect` 事件 [#customize-focus-and-reconnect-events]
28 |
29 | 只有很少的的配置需要你来处理,诸如 `isOnline`、`isVisible`、`initFocus` 以及 `initReconnect`。
30 |
31 | `isOnline` 和 `isVisible` 是两个返回布尔值的函数,它们用来确定应用程序是否是 "active" 的。默认情况下,如果不满足这些条件,SWR 将取消重新请求。
32 |
33 | 在使用 `initFocus` 和 `initReconnect` 时,还需要设置一个[自定义缓存 provider](/docs/advanced/cache)。可以使用空的 `Map()` 或任何你喜欢的。
34 |
35 | ```jsx
36 | new Map(),
39 | isOnline() {
40 | /* 自定义网络状态检测器 */
41 | return true
42 | },
43 | isVisible() {
44 | /* 自定义 visibility 状态检测器 */
45 | return true
46 | },
47 | initFocus(callback) {
48 | /* 向状态 provider 注册侦听器 */
49 | },
50 | initReconnect(callback) {
51 | /* 向状态 provider 注册侦听器 */
52 | }
53 | }}
54 | >
55 |
56 |
57 | ```
58 |
59 | 以 `initFocus` 为例:
60 |
61 | ```jsx
62 | import { AppState } from 'react-native'
63 |
64 | // ...
65 |
66 | new Map(),
69 | isVisible: () => { return true },
70 | initFocus(callback) {
71 | let appState = AppState.currentState
72 |
73 | const onAppStateChange = (nextAppState) => {
74 | /* 如果正在从后台或非 active 模式恢复到 active 模式 */
75 | if (appState.match(/inactive|background/) && nextAppState === 'active') {
76 | callback()
77 | }
78 | appState = nextAppState
79 | }
80 |
81 | // 订阅 app 状态更改事件
82 | const subscription = AppState.addEventListener('change', onAppStateChange)
83 |
84 | return () => {
85 | subscription.remove()
86 | }
87 | }
88 | }}
89 | >
90 |
91 |
92 | ```
93 |
94 | 关于 `initReconnect`,它需要第三方库例如 [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) 来订阅网络状态。具体实现和上面的例子类似:接收 `callback` 函数并在网络从离线状态恢复时触发它,然后 SWR 会启动重新请求以确保数据始终是最新的。
95 |
--------------------------------------------------------------------------------
/pages/docs/api.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # API
4 |
5 | ```js
6 | const { data, error, isLoading, isValidating, mutate } = useSWR(key, fetcher, options)
7 | ```
8 |
9 | ## 参数 [#parameters]
10 |
11 | - `key`: 请求的唯一 key string(或者是 function / array / null) [(详情)](/docs/arguments), [(高级用法)](/docs/conditional-fetching)
12 | - `fetcher`:(_可选_)一个请求数据的 Promise 返回函数 [(详情)](/docs/data-fetching)
13 | - `options`:(_可选_)该 SWR hook 的选项对象
14 |
15 | ## 返回值 [#return-values]
16 |
17 | - `data`: 通过 `fetcher` 用给定的 key 获取的数据(如未完全加载,返回 undefined)
18 | - `error`: `fetcher` 抛出的错误(或者是 undefined)
19 | - `isLoading`: 是否有一个正在进行中的请求且当前没有“已加载的数据“。预设数据及之前的数据不会被视为“已加载的数据“
20 | - `isValidating`: 是否有请求或重新验证加载
21 | - `mutate(data?, options?)`: 更改缓存数据的函数 [(详情)](/docs/mutation)
22 |
23 | 更多信息可以参考[这里](/docs/advanced/understanding).
24 |
25 | ## 选项 [#options]
26 |
27 | - `suspense = false`: 启用 React Suspense 模式 [(详情)](/docs/suspense)
28 | - `fetcher(args)`: fetcher 函数
29 | - `revalidateIfStale = true`: 即使存在陈旧数据,也自动重新验证[(详情)](/docs/revalidation#disable-automatic-revalidations)
30 | - `revalidateOnMount`: 在挂载组件时启用或禁用自动重新验证 [(详情)](/docs/revalidation#revalidate-on-mount)
31 | - `revalidateOnFocus = true`: 窗口聚焦时自动重新验证 [(详情)](/docs/revalidation)
32 | - `revalidateOnReconnect = true`: 浏览器恢复网络连接时自动重新验证(通过 `navigator.onLine`) [(详情)](/docs/revalidation)
33 | - `refreshInterval` [(详情)](/docs/revalidation):
34 | - 默认 disabled: `refreshInterval = 0`
35 | - 如果设置为数字,轮询间隔(以毫秒为单位)
36 | - 如果设置为函数,该函数将接收最新数据,并且应以毫秒为单位返回间隔
37 | - `refreshWhenHidden = false`: 窗口不可见时进行轮询(如果启用了 `refreshInterval`)
38 | - `refreshWhenOffline = false`: 浏览器离线时轮询(由 `navigator.onLine` 确定)
39 | - `shouldRetryOnError = true`: fetcher 有错误时重试
40 | - `dedupingInterval = 2000`: 删除一段时间内相同 key 的重复请求(以毫秒为单位)
41 | - `focusThrottleInterval = 5000`: 在一段时间内只重新验证一次(以毫秒为单位)
42 | - `loadingTimeout = 3000`: 超时触发 `onLoadingSlow` 事件(以毫秒为单位)
43 | - `errorRetryInterval = 5000`: 错误重试的时间间隔(以毫秒为单位)
44 | - `errorRetryCount`: 错误重试的最大次数
45 | - `fallback`: 多个回退数据的 key-value 对象[(示例)](/docs/with-nextjs)
46 | - `fallbackData`: 此 hook 需要返回的初始数据
47 | - `keepPreviousData = false`: 在新数据加载完成之前使用 key 上一次缓存过的数据 [(详情)](/docs/advanced/understanding#return-previous-data-for-better-ux)
48 | - `onLoadingSlow(key, config)`: 请求加载时间过长时的回调函数(参考 `loadingTimeout`)
49 | - `onSuccess(data, key, config)`: 请求成功完成时的回调函数
50 | - `onError(err, key, config)`: 请求返回错误时的回调函数
51 | - `onErrorRetry(err, key, config, revalidate, revalidateOps)`: 错误重试的处理函数
52 | - `onDiscarded(key)`: 请求由于竞态条件而被忽略时的回调函数
53 | - `compare(a, b)`: 比较函数,用来检测返回的数据何时已更改,以防止伪造的重新渲染。默认情况下使用 [stable-hash](https://github.com/shuding/stable-hash)。
54 | - `isPaused()`: 用于暂停所有数据请求,如果返回值为 `true`,请求的数据和错误都会被忽略。默认返回值为 `false`。
55 | - `use`: 中间件函数数组 [(详情)](/docs/middleware)
56 |
57 |
58 | 网络较慢(2G, {'<='} 70Kbps)时, 默认情况下 errorRetryInterval
为 10s, {' '}
59 | loadingTimeout
为 5s。
60 |
61 |
62 | 你还可以使用 [全局配置](/docs/global-configuration) 来提供默认选项。
63 |
--------------------------------------------------------------------------------
/pages/docs/arguments.en-US.mdx:
--------------------------------------------------------------------------------
1 | # Arguments
2 |
3 | By default, `key` will be passed to `fetcher` as the argument. So the following 3 expressions are equivalent:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## Multiple Arguments [#multiple-arguments]
12 |
13 | In some scenarios, it's useful to pass multiple arguments (can be any value or object) to the `fetcher` function.
14 | For example an authorized fetch request:
15 |
16 | ```js
17 | useSWR('/api/user', url => fetchWithToken(url, token))
18 | ```
19 |
20 | This is **incorrect**. Because the identifier (also the cache key) of the data is `'/api/user'`,
21 | even if `token` changes, SWR will still use the same key and return the wrong data.
22 |
23 | Instead, you can use an **array** as the `key` parameter, which contains multiple arguments of `fetcher`:
24 |
25 | ```js
26 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
27 | ```
28 |
29 | The `fetcher` function accepts the `key` parameter as is, and the cache key will also be associated with the entire `key` argument. In the above example, `url` and `token` are both tied to the cache key.
30 |
31 |
32 | In the previous versions (< 2.0.0), The `fetcher` function will receive the spreaded arguments from original `key` when the `key` argument is array type. E.g., key `[url, token]` will become 2 arguments `(url, token)` for `fetcher` function.
33 |
34 |
35 |
36 | ## Passing Objects [#passing-objects]
37 |
38 | import { Callout } from 'nextra-theme-docs'
39 |
40 |
41 | Since SWR 1.1.0, object-like keys will be serialized under the hood automatically.
42 |
43 |
44 | Say you have another function that fetches data with a user scope: `fetchWithUser(api, user)`. You can do the following:
45 |
46 | ```js
47 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
48 |
49 | // ...and then pass it as an argument to another useSWR hook
50 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
51 | ```
52 |
53 | You can directly pass an object as the key, and `fetcher` will receive that object too:
54 |
55 | ```js
56 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
57 | ```
58 |
59 |
60 | In older versions (< 1.1.0), SWR **shallowly** compares the arguments on every render, and triggers revalidation if any of them has changed.
61 |
62 |
--------------------------------------------------------------------------------
/pages/docs/arguments.es-ES.mdx:
--------------------------------------------------------------------------------
1 | # Argumentos
2 |
3 | Por defecto, `key` se pasará a `fetcher` como argumento. Así que las siguientes 3 expresiones son equivalentes:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## Argumentos múltiples [#multiple-arguments]
12 |
13 | En algunos escenarios, es útil pasar múltiples argumentos (puede pasar cualquier valor u objeto) a
14 | la función `fetcher`. Por ejemplo una solicitud de obtención autorizada:
15 |
16 | ```js
17 | useSWR('/api/user', url => fetchWithToken(url, token))
18 | ```
19 |
20 | Esto es **incorrecto**. Dado que el identificador (también la key del caché) de los datos es `'/api/user'`, incluso si el token cambia, SWR seguirá utilizando la misma key y devolverá los datos incorrectos.
21 |
22 | En su lugar, puedes utilizar un **array** como parámetro `key`, que contiene múltiples argumentos de `fetcher`:
23 |
24 | ```js
25 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
26 | ```
27 |
28 | La función `fetcher` acepta el parámetro `key` tal cual, y la clave de caché se asociará también al argumento `key` completo. En el ejemplo anterior, `url` y `token` están unidos a la clave de caché.
29 |
30 |
31 | En versiones anteriores (< 2), la función `fetcher` acepta el parámetro `key` como argumentos por separado
32 |
33 |
34 | ## Pasar objetos [#passing-objects]
35 |
36 | import { Callout } from 'nextra-theme-docs'
37 |
38 |
39 | Since SWR 1.1.0, object-like keys will be serialized under the hood automatically.
40 |
41 |
42 | Digamos que tienes otra función que obtiene datos con un ámbito de usuario: `fetchWithUser(api, user)`. Puedes hacer lo siguiente:
43 |
44 | ```js
45 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
46 |
47 | // ...y luego pasarlo como argumento a otro useSWR "hook"
48 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
49 | ```
50 |
51 | Puedes pasar directamente un objeto como clave, y `fetcher` también recibirá ese objeto:
52 |
53 | ```js
54 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
55 | ```
56 |
57 |
58 | En versiones anteriores (< 1.1.0), SWR compara superficialmente (shallowly) los argumentos en cada renderización, y activa la revalidación si alguno de ellos ha cambiado.
59 |
60 |
61 |
--------------------------------------------------------------------------------
/pages/docs/arguments.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Arguments
4 |
5 | Par défaut, `key` sera passé à `fetcher` comme argument. Donc les 3 expressions suivantes sont équivalentes:
6 |
7 | ```js
8 | useSWR('/api/user', () => fetcher('/api/user'))
9 | useSWR('/api/user', url => fetcher(url))
10 | useSWR('/api/user', fetcher)
11 | ```
12 |
13 | ## Arguments multiples [#multiple-arguments]
14 |
15 | Dans certains cas, il est utile de passer plusieurs arguments (pouvant être de n'importe quelle valeur ou objet) à la fonction `fetcher`. Par exemple, une requête fetch autorisée:
16 |
17 | ```js
18 | useSWR('/api/user', url => fetchWithToken(url, token))
19 | ```
20 |
21 | C'est **incorrect**. Parce que l'identifiant (également la clé de cache) des données est `'/api/user'`, même si `token` change, SWR utilisera toujours la même clé et renverra les mauvaises données.
22 |
23 | A la place, vous pouvez utiliser un **tableau** comme paramètre `key`, qui contient plusieurs arguments de `fetcher`:
24 |
25 | ```js
26 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
27 | ```
28 |
29 | La fonction `fetcher` accepte le paramètre `key` tel quel, et la clé de cache sera également associée à l'ensemble de l'argument `key`. Dans l'exemple ci-dessus, `url` et `token` sont tous deux liés à la clé de cache.
30 |
31 |
32 | Dans les précédentes versions (< 2.0.0), la fonction `fetcher` recevait les arguments étalés de la clé d'origine lorsque l'argument `key` était de type tableau. Par exemple, la clé `[url, token]` deviendra 2 arguments `(url, token)` pour la fonction `fetcher`.
33 |
34 |
35 |
36 | ## Passer des Objets [#passing-objects]
37 |
38 |
39 | Depuis SWR 1.1.0, les clés de type objet seront automatiquement sérialisées en arrière-plan.
40 |
41 |
42 | Disons que vous avez une autre fonction qui récupère des données avec une portée utilisateur: `fetchWithUser(api, user)`. Vous pouvez faire ce qui suit:
43 |
44 | ```js
45 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
46 |
47 | // ...et ensuite le passer en argument à un autre hook useSWR
48 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
49 | ```
50 |
51 | Vous pouvez également utiliser un objet comme clé, et `fetcher` recevra cet objet en tant qu'argument:
52 |
53 | ```js
54 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
55 | ```
56 |
57 |
58 | Dans les versions antérieures (< 1.1.0), SWR **superficiellement** compare les arguments à chaque rendu, et déclenche une revalidation si l'un d'entre eux a changé.
59 |
60 |
--------------------------------------------------------------------------------
/pages/docs/arguments.ja.mdx:
--------------------------------------------------------------------------------
1 | # 引数
2 |
3 | デフォルトで `key` は引数として `fetcher` に渡されます。したがって、次の三つの式は同等です:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## 複数の引数 [#multiple-arguments]
12 |
13 | 一部のシナリオでは、`fetcher` 関数に複数の引数(任意の値またはオブジェクト)を渡すと便利です。
14 | たとえば、認証されたフェッチリクエスト:
15 |
16 | ```js
17 | useSWR('/api/user', url => fetchWithToken(url, token))
18 | ```
19 |
20 | これは**正しくありません**。データの識別子(キャッシュキーも) `'/api/user'` であるため、
21 | `token` が変更された場合でも、SWR は同じキーを使用してしまい間違ったデータを返します。
22 |
23 | 代わりに、`fetcher` の複数の引数を含む**配列**を `key` パラメーターとして使用できます。
24 |
25 | ```js
26 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
27 | ```
28 |
29 | `fetcher` 関数は `key` パラメータをそのまま受け取り、キャッシュキーもまた `key` の引数全てと関連づけられます。上記の例では `url` と `token` の組み合わせがキャッシュキーとなります。
30 |
31 |
32 | In older versions (< 2), The `fetcher` function accepts the `key` parameter as arguments separately
33 |
34 |
35 | ## オブジェクトの受け渡し [#passing-objects]
36 |
37 | import { Callout } from 'nextra-theme-docs'
38 |
39 |
40 | SWR 1.1.0 からは、オブジェクトのようなキーは内部で自動的にシリアライズされます。
41 |
42 |
43 | あるユーザースコープでデータを取得する別の関数があるとします: `fetchWithUser(api, user)`。その場合、以下のようにできます:
44 |
45 | ```js
46 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
47 |
48 | // ...次に、それを引数として別の useSWR フックに渡します
49 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
50 | ```
51 |
52 | オブジェクトをキーとして直接渡すことができ、`fetcher` はそのオブジェクトを受け取ります:
53 |
54 | ```js
55 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
56 | ```
57 |
58 |
59 | 古いバージョン(< 1.1.0)では、SWR はすべてのレンダリングで引数を**浅く**比較し、いずれかが変更された場合は再検証を実行します。
60 |
61 |
62 |
--------------------------------------------------------------------------------
/pages/docs/arguments.ko.mdx:
--------------------------------------------------------------------------------
1 | # 인자
2 |
3 | 기본값으로, `key`는 인자로써 `fetcher`에 전달됩니다. 따라서 다음 세 가지 표현식은 동일합니다.
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## 다중 인자 [#multiple-arguments]
12 |
13 | 어떤 시나리오에서는 `fetcher` 함수에 여러 인자(어떠한 값이나 객체도 가능)를 전달하는 것이 유용합니다.
14 | 인증된 가져오기 요청 예시입니다:
15 |
16 | ```js
17 | useSWR('/api/user', url => fetchWithToken(url, token))
18 | ```
19 |
20 | 이는 **올바르지 않습니다**. 왜냐하면 데이터의 식별자(또한 캐시 키)가 `'/api/user'`이고,
21 | 만약 `token`이 변경되어도 SWR은 여전히 동일한 키를 사용하기 때문에 잘못된 데이터를 반환합니다.
22 |
23 | 대신에 `fetcher`의 다중 인자를 포함하는 **배열**을 `key` 파라미터로 사용할 수 있습니다.
24 |
25 | ```js
26 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
27 | ```
28 |
29 | `fetcher` 함수는 `key` 파라미터를 그대로 받아들이며, 캐시 키도 전체 `key` 인수와 연관됩니다. 위의 예에서 `url`과 `token`은 둘 다 캐시 키에 들어맞습니다.
30 |
31 |
32 | 이전 버전(< 2)에서는 `fetcher` 함수는 `key` 파라미터를 인수로 허용합니다
33 |
34 |
35 | ## 객체 전달 [#passing-objects]
36 |
37 | import { Callout } from 'nextra-theme-docs'
38 |
39 |
40 | SWR 1.1.0부터, 유사 객체 키들은 내부에서 자동으로 직렬화됩니다.
41 |
42 |
43 | 사용자 범위로 데이터를 가져오는 `fetchWithUser(api, user)` 함수가 있다고 해봅시다. 다음과 같이 사용할 수 있습니다.
44 |
45 | ```js
46 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
47 |
48 | // ...그 후, 이를 또 다른 useSWR hook의 인자로 전달하세요
49 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
50 | ```
51 |
52 | 객체를 키로써 바로 전달할 수 있으며 `fetcher`가 그 객체를 받습니다.
53 |
54 | ```js
55 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
56 | ```
57 |
58 |
59 | 이전 버전(< 1.1.0)에서는, SWR은 렌더링할 때마다 인자들을 **얕게** 비교하며, 변경이 있으면 갱신을 트리거합니다.
60 |
61 |
--------------------------------------------------------------------------------
/pages/docs/arguments.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | # Argumentos
2 |
3 | Por padrão, `key` será passado para `fetcher` como argumento. Então as 3 expressões a seguir são equivalentes:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## Múltiplos Argumentos [#multiple-arguments]
12 |
13 | Em alguns cenários, é útil passar vários argumentos (pode ser qualquer valor ou objeto) para a função `fetcher`.
14 | Por exemplo, uma requisição de fetch autorizada:
15 |
16 | ```js
17 | useSWR('/api/user', url => fetchWithToken(url, token))
18 | ```
19 |
20 | Isso é **incorreto**. Porque o identificador (também a cache key) do dado é `'/api/user'`,
21 | mesmo se `token` mudar, SWR ainda usará a mesma chave e retornará o dado errado.
22 |
23 | Ao invés disso, você pode usar um array como o parâmetro `key`, que contém vários argumentos para a função `fetcher`.
24 |
25 | ```js
26 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
27 | ```
28 |
29 | A função `fetcher` aceita o parâmetro `key` como é, e a chave de cache também será associada com o argumento `key` inteiro. No exemplo acima, `url` e `token` estão associados à chave de cache.
30 |
31 |
32 | Em versões antigas (< 2), a função `fetcher` aceita o parâmetro `key` como argumentos separadamente
33 |
34 |
35 | ## Passando Objetos [#passing-objects]
36 |
37 | import { Callout } from 'nextra-theme-docs'
38 |
39 |
40 | Desde a versão 1.1.0, chaves de objeto serão serializadas por baixo dos panos automaticamente.
41 |
42 |
43 | Digamos que você tenha outra função que busca dados com um escopo de usuário: `fetchWithUser(api, user)`. Você pode fazer o seguinte:
44 |
45 | ```js
46 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
47 |
48 | // ...e então passá-lo como argumento para outro hook useSWR
49 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
50 | ```
51 |
52 | Você pode passar diretamente um objeto como chave, e `fetcher` receberá esse objeto também:
53 |
54 | ```js
55 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
56 | ```
57 |
58 |
59 | Em versões antigas (< 1.1.0), SWR compara os argumentos **superficialmente** em cada renderização e aciona a revalidação se algum deles foi alterado.
60 |
61 |
--------------------------------------------------------------------------------
/pages/docs/arguments.ru.mdx:
--------------------------------------------------------------------------------
1 | # Аргументы
2 |
3 | По умолчанию `key` будет передан в `fetcher` в качестве аргумента. Итак, следующие 3 выражения эквивалентны:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## Множественные аргументы [#multiple-arguments]
12 |
13 | В некоторых сценариях полезно передать несколько аргументов (может быть любое значение или объект) в `fetcher`. Например, запрос на выборку с авторизацией:
14 |
15 | ```js
16 | useSWR('/api/user', url => fetchWithToken(url, token))
17 | ```
18 |
19 | Это **неверно**. Поскольку идентификатор (также ключ кеша) данных - это `'/api/user'`,
20 | даже если `token` изменится, SWR все равно будет использовать тот же ключ и возвращать неверные данные.
21 |
22 | Вместо этого вы можете использовать **массив** в качестве параметра `key`, который содержит несколько аргументов `fetcher`:
23 |
24 | ```js
25 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
26 | ```
27 |
28 | Функция `fetcher` принимает параметр `key` как есть, и ключ кеша также будет связан со всем аргументом `key`. В приведенном выше примере `url` и `token` тесно связаны с ключом кеша.
29 |
30 |
31 | В более старых версиях (< 2) функция `fetcher` принимает параметр `key` в качестве аргументов отдельно
32 |
33 |
34 | ## Передача объектов [#passing-objects]
35 |
36 | import { Callout } from 'nextra-theme-docs'
37 |
38 |
39 | Начиная с версии SWR 1.1.0 объектно-подобные ключи будут автоматически сериализоваться.
40 |
41 |
42 | Допустим, у вас есть другая функция, которая делает выборку данных с областью действия пользователя: `fetchWithUser(api, user)`. Вы можете сделать следующее:
43 |
44 | ```js
45 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
46 |
47 | // ...затем передать его в качестве аргумента другому хуку useSWR
48 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
49 | ```
50 |
51 | Вы можете напрямую передать объект в качестве ключа, и `fetcher` тоже получит этот объект:
52 |
53 | ```js
54 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
55 | ```
56 |
57 |
58 | В более старых версиях (< 1.1.0) SWR **поверхностно** сравнивает аргументы при каждом рендеринге и запускает повторную проверку, если какой-либо из них изменился.
59 |
60 |
--------------------------------------------------------------------------------
/pages/docs/arguments.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | # 参数
2 |
3 | 默认情况下,`key` 将作为参数传递给 `fetcher`。所以下面这 3 个表达式是等价的:
4 |
5 | ```js
6 | useSWR('/api/user', () => fetcher('/api/user'))
7 | useSWR('/api/user', url => fetcher(url))
8 | useSWR('/api/user', fetcher)
9 | ```
10 |
11 | ## 多个参数 [#multiple-arguments]
12 |
13 | 在某些场景中,向 `fetcher` 函数传递多个参数(可以是任何值或对象)非常有用。例如授权请求:
14 |
15 | ```js
16 | useSWR('/api/user', url => fetchWithToken(url, token))
17 | ```
18 |
19 | 这是 **错误的**。 因为数据的标识符(也是缓存 key)是 `'/api/user'`,所以即使 `token` 变了,SWR 仍然会使用相同的 key 并返回错误的数据。
20 |
21 | 相反,你可以使用一个 **数组** 作为参数 `key`,它包含 `fetcher` 的多个参数:
22 |
23 | ```js
24 | const { data: user } = useSWR(['/api/user', token], ([url, token]) => fetchWithToken(url, token))
25 | ```
26 |
27 | `fetcher` 函数会按原样接受 `key` 参数,并且缓存 `key` 也将与整个 `key` 参数相关联。在上面的例子中,`url` 和 `token` 都与缓存 `key` 相关联。
28 |
29 |
30 | 在之前的版本 (< 2.0.0) 中,当 key 参数是数组类型时,`fetcher` 函数将以展开参数的形式接收到原始 `key`。例如,key `[url, token]` 会变成 `fetcher` 函数的两个参数 `(url, token)`。
31 |
32 |
33 | ## 传入对象 [#passing-objects]
34 |
35 | import { Callout } from 'nextra-theme-docs'
36 |
37 |
38 | 从 SWR 1.1.0 开始,object 类型的 keys 可以在内部自动被序列化。
39 |
40 |
41 | 假设你还有另一个使用用户范围来请求数据的函数:`fetchWithUser(api, user)`。你可以执行以下操作:
42 |
43 | ```js
44 | const { data: user } = useSWR(['/api/user', token], fetchWithToken)
45 |
46 | // ...然后将其作为参数传递给另一个 useSWR hook
47 | const { data: orders } = useSWR(user ? ['/api/orders', user] : null, fetchWithUser)
48 | ```
49 |
50 | 你可以直接传递一个对象作为 key,`fetcher` 也会接收该对象:
51 |
52 | ```js
53 | const { data: orders } = useSWR({ url: '/api/orders', args: user }, fetcher)
54 | ```
55 |
56 |
57 | 在旧版本(< 1.1.0)中,SWR 会**浅**比较每次渲染时的参数,如果其中任何一个发生了变化,就会触发重新验证。
58 |
59 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.en-US.mdx:
--------------------------------------------------------------------------------
1 | # Conditional Fetching
2 |
3 | ## Conditional [#conditional]
4 |
5 | Use `null` or pass a function as `key` to conditionally fetch data. If the function throws or returns a falsy value, SWR will not start the request.
6 |
7 | ```js
8 | // conditionally fetch
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...or return a falsy value
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...or throw an error when user.id is not defined
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## Dependent [#dependent]
19 |
20 | SWR also allows you to fetch data that depends on other data. It ensures the maximum possible parallelism (avoiding waterfalls), as well as serial fetching when a piece of dynamic data is required for the next data fetch to happen.
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // When passing a function, SWR will use the return
27 | // value as `key`. If the function throws or returns
28 | // falsy, SWR will know that some dependencies are not
29 | // ready. In this case `user.id` throws when `user`
30 | // isn't loaded.
31 |
32 | if (!projects) return 'loading...'
33 | return 'You have ' + projects.length + ' projects'
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.es-ES.mdx:
--------------------------------------------------------------------------------
1 | # Búsqueda Condicional
2 |
3 | ## Condicional [#conditional]
4 |
5 | Utilice `null` o pase una función como `key` para obtener datos de forma condicional.
6 | Si la función lanza o devuelve un falsy value, SWR no iniciará la petición.
7 |
8 |
9 | ```js
10 | // conditionally fetch
11 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
12 |
13 | // ...o devuelve un falsy value
14 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
15 |
16 | // ...o lanza un error cuando user.id no está definifo
17 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
18 | ```
19 |
20 | ## Dependiente [#dependent]
21 |
22 | SWR también permite obtener datos que dependen de otros datos. Garantiza el máximo paralelismo posible (evitando las cascadas), así como la obtención en serie cuando se necesita un dato dinámico para que se produzca la siguiente obtención de datos.
23 |
24 | ```js
25 | function MyProjects () {
26 | const { data: user } = useSWR('/api/user')
27 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
28 | // Al pasar una función, SWR utilizará el valor devuelto
29 | // como `key`. Si la función lanza o devuelve
30 | // falsy, SWR sabrá que algunas dependencias no estan
31 | // ready. En este caso `user.id` lanza cuando `user`
32 | // no este cargado.
33 |
34 | if (!projects) return 'loading...'
35 | return 'You have ' + projects.length + ' projects'
36 | }
37 | ```
38 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | # Récupération de données Conditionnelle
2 |
3 | ## Condition [#conditional]
4 |
5 | Utilisez `null` ou passez une fonction en tant que `key` pour récupérer les données de manière conditionnelle. Si la fonction échoue ou renvoie une valeur falsy, SWR ne démarrera pas la requête.
6 |
7 | ```js
8 | // récupération conditionnelle
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...ou renvoie une valeur falsy
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...ou renvoie une erreur quant user.id n'est pas défini
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## Dépendant [#dependent]
19 |
20 | SWR vous permet également de récupérer des données qui dépendentes d'autres données. Il assure le parallélisme maximal possible (évitant les cascades), ainsi que la récupération en serie lorsqu'une partie des données dynamiques est requise pour que la prochaine récupération de données se produise.
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // Quand on passe une fonction, SWR utilisera
27 | // la valeur de retour comme `key`. Si la fonction
28 | // échoue ou renvoie une valeur falsy, SWR saura
29 | // que certaines dépendances ne sont pas prêtes.
30 | // Dans ce cas, `user.id` échoue quand `user`
31 | // n'est pas chargé.
32 |
33 | if (!projects) return 'chargement...'
34 | return 'Vous avez ' + projects.length + ' projets'
35 | }
36 | ```
37 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.ja.mdx:
--------------------------------------------------------------------------------
1 | # 条件付きフェッチ
2 |
3 | ## 条件付き [#conditional]
4 |
5 | 条件付きでデータを取得するには `null` を使用するか、 `key` として関数を渡します。関数がスローまたは falsy な値を返した場合、 SWR はリクエストを開始しません。
6 |
7 | ```js
8 | // 条件付きでフェッチする
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...または、falsyな値を返します
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...または、user.id が定義されてない場合にスローします
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## 依存性 [#dependent]
19 |
20 | SWR では、他のデータに依存するデータをフェッチすることもできます。これにより、可能な限り最大の並列性(ウォーターフォールの回避)を確保するとともに、次のデータフェッチのために動的なデータの一部が必要な場合には、シリアルフェッチを行うことができます。
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // 関数を渡す場合、SWRは返り値を`key`として使用します。
27 | // 関数がスローまたはfalsyな値を返す場合、
28 | // SWRはいくつかの依存関係が準備できてないことを知ることができます。
29 | // この例では、`user.id`は`user`がロードされてない時にスローします。
30 |
31 | if (!projects) return 'loading...'
32 | return 'You have ' + projects.length + ' projects'
33 | }
34 | ```
35 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.ko.mdx:
--------------------------------------------------------------------------------
1 | # 조건부 가져오기
2 |
3 | ## 조건부 [#conditional]
4 |
5 | `null`을 사용하거나 함수를 `key`로 전달하여 데이터를 조건부로 가져옵니다. 함수가 falsy 값을 던지거나 반환하면 SWR은 요청을 시작하지 않습니다.
6 |
7 | ```js
8 | // 조건부 가져오기
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...또는 falsy 값 반환
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...또는 user.id가 정의되지 않았을 때 에러 throw
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## 의존 [#dependent]
19 |
20 | SWR은 다른 데이터에 의존하는 데이터를 가져오는 것 또한 허용합니다. 이는 다음 데이터 가져오기를 위한 동적 데이터 조각이 필요할 때, 직렬 가져오기뿐만 아니라 가능한 최대 병렬 처리(폭포수 방지)를 보장합니다.
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // 함수를 전달할 때, SWR은 반환 값을 `key`로 사용합니다.
27 | // 함수가 falsy를 던지거나 반환한다면,
28 | // SWR은 일부 의존성이 준비되지 않은 것을 알게 됩니다.
29 | // 이 예시의 경우 `user.id`는 `user`가 로드되지 않았을 때
30 | // 에러를 던집니다.
31 |
32 | if (!projects) return 'loading...'
33 | return 'You have ' + projects.length + ' projects'
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | # Data Fetching Condicional
2 |
3 | ## Conditional [#conditional]
4 |
5 | Use `null` ou passe a função como `key` para obter dados condicionais. Se a função lança ou retorna um valor `falsy` (um valor que se traduz em falso quando avaliado em um contexto Boolean), SWR não iniciará a requisição.
6 |
7 | ```js
8 | // fetch condicional
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...or retornar um valor falsy
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...or lançar um erro quando user.id não está definido
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## Dependente [#dependent]
19 |
20 | SWR também permite você obter dados que dependem de outros dados. Ele garante o máximo possível de paralelismo (evitando o waterfall), assim como a sequência de requisições quando um pedaço de dados dinâmico é necessário para que a próxima requisição de dados seja feita.
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 |
27 | // Quando passamos uma função, SWR usará o valor de retorno
28 | // como `key`. Se a função lança ou retorna um valor falsy,
29 | // SWR saberá que algumas dependências não estão prontas.
30 | // No caso, `user.id` lança quando `user` não está carregado.
31 |
32 | if (!projects) return 'carregando...'
33 | return 'Você possui ' + projects.length + ' projetos'
34 | }
35 | ```
36 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.ru.mdx:
--------------------------------------------------------------------------------
1 | # Условная выборка
2 |
3 | ## Условная [#conditional]
4 |
5 | Используйте `null` или передайте функцию в качестве `key` для условной выборки данных. Если функция выводит ошибку или возвращает ложное значение, SWR не отправляет запрос.
6 |
7 | ```js
8 | // условная выборка
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...или вернуть ложное значение
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ...или вывести ошибку, если user.id не определен
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## Зависимая [#dependent]
19 |
20 | SWR также позволяет получать данные, которые зависят от других данных. Это обеспечивает максимально возможный параллелизм (избегая водопадов), а также последовательную выборку, когда для следующей выборки данных требуется фрагмент динамических данных.
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // При передаче функции SWR будет использовать возвращаемое значение
27 | // как `key`. Если функция выдает ошибку или возвращает ложь,
28 | // SWR будет знать, что некоторые зависимости не готовы.
29 | // В этом случае `user.id` выдает ошибку, когда `user` не загружен.
30 |
31 | if (!projects) return 'загрузка...'
32 | return 'У вас ' + projects.length + ' проектов'
33 | }
34 | ```
35 |
--------------------------------------------------------------------------------
/pages/docs/conditional-fetching.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | # 条件数据请求
2 |
3 | ## 按需请求 [#conditional]
4 |
5 | 使用 `null` 或传一个函数作为 `key` 来有条件地请求数据。如果函数抛出错误或返回 falsy 值,SWR 将不会启动请求。
6 |
7 | ```js
8 | // 有条件的请求
9 | const { data } = useSWR(shouldFetch ? '/api/data' : null, fetcher)
10 |
11 | // ...或返回一个 falsy 值
12 | const { data } = useSWR(() => shouldFetch ? '/api/data' : null, fetcher)
13 |
14 | // ... 或在 user.id 未定义时抛出错误
15 | const { data } = useSWR(() => '/api/data?uid=' + user.id, fetcher)
16 | ```
17 |
18 | ## 依赖请求 [#dependent]
19 |
20 | SWR 还允许请求依赖于其他数据的数据。当需要一段动态数据才能进行下一次数据请求时,它可以确保最大程度的并行性(avoiding waterfalls)以及串行请求。
21 |
22 | ```js
23 | function MyProjects () {
24 | const { data: user } = useSWR('/api/user')
25 | const { data: projects } = useSWR(() => '/api/projects?uid=' + user.id)
26 | // 传递函数时,SWR 会用返回值作为 `key`。
27 | // 如果函数抛出错误或返回 falsy 值,SWR 会知道某些依赖还没准备好。
28 | // 这种情况下,当 `user`未加载时,`user.id` 抛出错误
29 |
30 | if (!projects) return 'loading...'
31 | return 'You have ' + projects.length + ' projects'
32 | }
33 | ```
34 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.en-US.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # Data Fetching
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | This is the very fundamental API of SWR. The `fetcher` here is an async function that **accepts the `key`** of SWR, and returns the data.
11 |
12 | The returned value will be passed as `data`, and if it throws, it will be caught as `error`.
13 |
14 |
15 | Note that fetcher
can be omitted from the parameters if it's{' '}
16 | provided globally.
17 |
18 |
19 | ## Fetch [#fetch]
20 |
21 | You can use any library to handle data fetching, for example a `fetch` polyfill [developit/unfetch](https://github.com/developit/unfetch):
22 |
23 | ```js
24 | import fetch from 'unfetch'
25 |
26 | const fetcher = url => fetch(url).then(r => r.json())
27 |
28 | function App () {
29 | const { data, error } = useSWR('/api/data', fetcher)
30 | // ...
31 | }
32 | ```
33 |
34 |
35 | If you are using Next.js , you don't need to import this polyfill:
36 | New Built-In Polyfills: fetch(), URL, and Object.assign
37 |
38 |
39 | ## Axios [#axios]
40 |
41 | ```js
42 | import axios from 'axios'
43 |
44 | const fetcher = url => axios.get(url).then(res => res.data)
45 |
46 | function App () {
47 | const { data, error } = useSWR('/api/data', fetcher)
48 | // ...
49 | }
50 | ```
51 |
52 | ## GraphQL [#graphql]
53 |
54 | Or using GraphQL with libs like [graphql-request](https://github.com/prisma-labs/graphql-request):
55 |
56 | ```js
57 | import { request } from 'graphql-request'
58 |
59 | const fetcher = query => request('/api/graphql', query)
60 |
61 | function App () {
62 | const { data, error } = useSWR(
63 | `{
64 | Movie(title: "Inception") {
65 | releaseDate
66 | actors {
67 | name
68 | }
69 | }
70 | }`,
71 | fetcher
72 | )
73 | // ...
74 | }
75 | ```
76 |
77 | _If you want to pass variables to a GraphQL query, check out [Multiple Arguments](/docs/arguments)._
78 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.es-ES.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # Obtención De Datos
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | Esta es la API fundamental de SWR. El `fetcher` aquí es una función asíncrona que **acepta el `key`** de SWR,
11 | y devuelve los datos.
12 |
13 | El valor devuelto será pasado como `data`, y si lanza, será capturado como `error`.
14 |
15 |
16 | Tenga en cuenta que el fetcher
puede ser omitido de los parámetros si se
17 | proporciona globalmente.
18 |
19 |
20 | ## Fetch [#fetch]
21 |
22 | Puedes utilizar cualquier librería para manejar data fetching, por ejemplo un `fetch` polyfill [developit/unfetch](https://github.com/developit/unfetch):
23 |
24 | ```js
25 | import fetch from 'unfetch'
26 |
27 | const fetcher = url => fetch(url).then(r => r.json())
28 |
29 | function App () {
30 | const { data, error } = useSWR('/api/data', fetcher)
31 | // ...
32 | }
33 | ```
34 |
35 |
36 | Si estás usando Next.js , no necesita importar este polyfill:
37 | Nuevos Polyfills Incorporados: fetch(), URL, y Object.assign
38 |
39 |
40 | ## Axios [#axios]
41 |
42 | ```js
43 | import axios from 'axios'
44 |
45 | const fetcher = url => axios.get(url).then(res => res.data)
46 |
47 | function App () {
48 | const { data, error } = useSWR('/api/data', fetcher)
49 | // ...
50 | }
51 | ```
52 |
53 | ## GraphQL [#graphql]
54 |
55 | O utilizando GraphQL con librerías como [graphql-request](https://github.com/prisma-labs/graphql-request):
56 |
57 | ```js
58 | import { request } from 'graphql-request'
59 |
60 | const fetcher = query => request('/api/graphql', query)
61 |
62 | function App () {
63 | const { data, error } = useSWR(
64 | `{
65 | Movie(title: "Inception") {
66 | releaseDate
67 | actors {
68 | name
69 | }
70 | }
71 | }`,
72 | fetcher
73 | )
74 | // ...
75 | }
76 | ```
77 |
78 | _Si quiere pasar variables a una query GraphQL, consulte [Argumentos múltiples](/docs/arguments)._
79 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # Récupération des données
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | C'est l'API fondamentale de SWR. Le `fetcher` est une fonction asynchrone qui **accepte la `key`** de SWR, et retourne les données.
11 |
12 | La valeur retournée sera passée en tant que `data`, et si elle lance une erreur, elle sera attrapée en tant que `error`.
13 |
14 |
15 | Notez que fetcher
peut être omis des paramètres s'il est{' '}
16 | fourni globalement.
17 |
18 |
19 | ## Récupération [#fetch]
20 |
21 | Vous pouvez utiliser n'importe quelle bibliothèque pour gérer la récupération des données, par exemple un polyfill `fetch` [developit/unfetch](https://github.com/developit/unfetch):
22 |
23 | ```js
24 | import fetch from 'unfetch'
25 |
26 | const fetcher = url => fetch(url).then(r => r.json())
27 |
28 | function App () {
29 | const { data, error } = useSWR('/api/data', fetcher)
30 | // ...
31 | }
32 | ```
33 |
34 |
35 | Si vous utilisez Next.js , vous n'avez pas besoin d'importer ce polyfill :
36 | New Built-In Polyfills: fetch(), URL, and Object.assign
37 | If you are using Next.js , you don't need to import this polyfill:
38 |
39 |
40 | ## Axios [#axios]
41 |
42 | ```js
43 | import axios from 'axios'
44 |
45 | const fetcher = url => axios.get(url).then(res => res.data)
46 |
47 | function App () {
48 | const { data, error } = useSWR('/api/data', fetcher)
49 | // ...
50 | }
51 | ```
52 |
53 | ## GraphQL [#graphql]
54 |
55 | Ou avec GraphQL et des bibliothèques comme [graphql-request](https://github.com/prisma-labs/graphql-request):
56 |
57 | ```js
58 | import { request } from 'graphql-request'
59 |
60 | const fetcher = query => request('/api/graphql', query)
61 |
62 | function App () {
63 | const { data, error } = useSWR(
64 | `{
65 | Movie(title: "Inception") {
66 | releaseDate
67 | actors {
68 | name
69 | }
70 | }
71 | }`,
72 | fetcher
73 | )
74 | // ...
75 | }
76 | ```
77 |
78 | _Si vous voulez passer des variables à une requête GraphQL, consultez [Multiple Arguments](/docs/arguments)._
79 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.ja.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # データフェッチ
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | こちらは SWR のとても基本的な API です。この `fetcher` は非同期関数であり、SWR の **`key` を受け取り**データを返します。
11 |
12 | 返り値は `data` として渡されます。もし例外が投げられた場合は `error` としてキャッチされます。
13 |
14 |
15 | fetcher
が{' '}
16 | グローバルで提供されている{' '}
17 | 場合は、パラメーターから省略できることに注意してください。
18 |
19 |
20 | ## Fetch [#fetch]
21 |
22 | fetch ポリフィル [developit/unfetch](https://github.com/developit/unfetch) など、任意のライブラリを使用してデータのフェッチを処理できます:
23 |
24 | ```js
25 | import fetch from 'unfetch'
26 |
27 | const fetcher = url => fetch(url).then(r => r.json())
28 |
29 | function App () {
30 | const { data, error } = useSWR('/api/data', fetcher)
31 | // ...
32 | }
33 | ```
34 |
35 |
36 | Next.js を使用している場合は、次のポリフィルをインポートする必要はありません:
37 | New Built-In Polyfills: fetch(), URL, and Object.assign
38 |
39 |
40 | ## Axios [#axios]
41 |
42 | ```js
43 | import axios from 'axios'
44 |
45 | const fetcher = url => axios.get(url).then(res => res.data)
46 |
47 | function App () {
48 | const { data, error } = useSWR('/api/data', fetcher)
49 | // ...
50 | }
51 | ```
52 |
53 | ## GraphQL [#graphql]
54 |
55 | または、[graphql-request](https://github.com/prisma-labs/graphql-request) のようなライブラリで GraphQL を使う場合:
56 |
57 | ```js
58 | import { request } from 'graphql-request'
59 |
60 | const fetcher = query => request('/api/graphql', query)
61 |
62 | function App () {
63 | const { data, error } = useSWR(
64 | `{
65 | Movie(title: "Inception") {
66 | releaseDate
67 | actors {
68 | name
69 | }
70 | }
71 | }`,
72 | fetcher
73 | )
74 | // ...
75 | }
76 | ```
77 |
78 | _変数を GraphQL クエリーに渡したい場合は、[複数の引数](/docs/arguments) を確認してください。_
79 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.ko.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # 데이터 가져오기
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | 이것은 SWR의 아주 핵심적인 API입니다. 여기의 `fetcher`는 SWR의 **`key`를 받고** 데이터를 반환하는 비동기 함수입니다.
11 |
12 | 반환된 값은 `data`로 전달되며, 만약 throws라면 `error`로 잡힙니다.
13 |
14 |
15 | fetcher
가 전역으로 제공된다면
16 | 파라미터에서 생략할 수 있습니다.
17 |
18 |
19 | ## 가져오기 [#fetch]
20 |
21 | 데이터 가져오기를 다루는 어떠한 라이브러리든 사용할 수 있습니다. `fetch` 폴리필 [developit/unfetch](https://github.com/developit/unfetch)를 예로 들어보겠습니다.
22 |
23 | ```js
24 | import fetch from 'unfetch'
25 |
26 | const fetcher = url => fetch(url).then(r => r.json())
27 |
28 | function App () {
29 | const { data, error } = useSWR('/api/data', fetcher)
30 | // ...
31 | }
32 | ```
33 |
34 |
35 | Next.js 를 사용 중이라면 폴리필을 임포트할 필요가 없습니다.
36 | 새로운 내장 폴리필: fetch(), URL, Object.assign
37 |
38 |
39 | ## Axios [#axios]
40 |
41 | ```js
42 | import axios from 'axios'
43 |
44 | const fetcher = url => axios.get(url).then(res => res.data)
45 |
46 | function App () {
47 | const { data, error } = useSWR('/api/data', fetcher)
48 | // ...
49 | }
50 | ```
51 |
52 | ## GraphQL [#graphql]
53 |
54 | 또는 [graphql-request](https://github.com/prisma-labs/graphql-request)와 같은 라이브러리로 GraphQL 사용
55 |
56 | ```js
57 | import { request } from 'graphql-request'
58 |
59 | const fetcher = query => request('/api/graphql', query)
60 |
61 | function App () {
62 | const { data, error } = useSWR(
63 | `{
64 | Movie(title: "Inception") {
65 | releaseDate
66 | actors {
67 | name
68 | }
69 | }
70 | }`,
71 | fetcher
72 | )
73 | // ...
74 | }
75 | ```
76 |
77 | _GraphQL 쿼리로 변수를 전달하고자 한다면 [다중 인자](/docs/arguments)를 확인하세요._
78 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # Data Fetching
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | Essa é a API mais fundamental do SWR. A função `fetcher` aqui é uma função assíncrona que **aceita a chave do SWR**, e retorna os dados.
11 |
12 | O valor retornado será passado como `data`, e se ele der erro, será capturado como `error`.
13 |
14 |
15 | Note que fetcher
pode ser omitido dos parâmetros se ele for{' '}
16 | fornecido globalmente.
17 |
18 |
19 | ## Fetch [#fetch]
20 |
21 | Você pode usar qualquer biblioteca para lidar com a obtenção de dados, por exemplo o `fetch` polyfill [developit/unfetch](https://github.com/developit/unfetch):
22 |
23 | ```js
24 | import fetch from 'unfetch'
25 |
26 | const fetcher = url => fetch(url).then(r => r.json())
27 |
28 | function App () {
29 | const { data, error } = useSWR('/api/data', fetcher)
30 | // ...
31 | }
32 | ```
33 |
34 |
35 | Se você está usando Next.js , você não precisa importar este polyfill:
36 | New Built-In Polyfills: fetch(), URL, and Object.assign
37 |
38 |
39 | ## Axios [#axios]
40 |
41 | ```js
42 | import axios from 'axios'
43 |
44 | const fetcher = url => axios.get(url).then(res => res.data)
45 |
46 | function App () {
47 | const { data, error } = useSWR('/api/data', fetcher)
48 | // ...
49 | }
50 | ```
51 |
52 | ## GraphQL [#graphql]
53 |
54 | Ou usando GraphQL com bibliotecas como [graphql-request](https://github.com/prisma-labs/graphql-request):
55 |
56 | ```js
57 | import { request } from 'graphql-request'
58 |
59 | const fetcher = query => request('/api/graphql', query)
60 |
61 | function App () {
62 | const { data, error } = useSWR(
63 | `{
64 | Movie(title: "Inception") {
65 | releaseDate
66 | actors {
67 | name
68 | }
69 | }
70 | }`,
71 | fetcher
72 | )
73 | // ...
74 | }
75 | ```
76 |
77 | _Se você quiser passar variáveis para uma query GraphQL, cheque [Argumentos Múltiplos](/docs/arguments)._
78 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.ru.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # Выборка данных
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | Это самый фундаментальный API SWR. `fetcher` здесь представляет собой асинхронную функцию, которая **принимает `key`** SWR и возвращает данные.
11 |
12 | Возвращаемое значение будет передано как `data`, и если оно будет выброшено, оно будет перехвачено как `error`.
13 |
14 |
15 | Обратите внимание, что fetcher
можно не указывать в параметрах, если он{' '}
16 | предоставляется глобально.
17 |
18 |
19 | ## Выборка (Fetch) [#fetch]
20 |
21 | Вы можете использовать любую библиотеку для обработки выборки данных, например, полифил `fetch` — [developit/unfetch](https://github.com/developit/unfetch):
22 |
23 | ```js
24 | import fetch from 'unfetch'
25 |
26 | const fetcher = url => fetch(url).then(r => r.json())
27 |
28 | function App () {
29 | const { data, error } = useSWR('/api/data', fetcher)
30 | // ...
31 | }
32 | ```
33 |
34 |
35 | Если вы используете Next.js , вам не нужно импортировать этот полифил:
36 | Новые встроенные полифилы: fetch(), URL, и Object.assign
37 |
38 |
39 | ## Axios [#axios]
40 |
41 | ```js
42 | import axios from 'axios'
43 |
44 | const fetcher = url => axios.get(url).then(res => res.data)
45 |
46 | function App () {
47 | const { data, error } = useSWR('/api/data', fetcher)
48 | // ...
49 | }
50 | ```
51 |
52 | ## GraphQL [#graphql]
53 |
54 | Или используйте GraphQL с такими библиотеками, как [graphql-request](https://github.com/prisma-labs/graphql-request):
55 |
56 | ```js
57 | import { request } from 'graphql-request'
58 |
59 | const fetcher = query => request('/api/graphql', query)
60 |
61 | function App () {
62 | const { data, error } = useSWR(
63 | `{
64 | Movie(title: "Начало") {
65 | releaseDate
66 | actors {
67 | name
68 | }
69 | }
70 | }`,
71 | fetcher
72 | )
73 | // ...
74 | }
75 | ```
76 |
77 | _Если вы хотите передавать переменные в запрос GraphQL, ознакомьтесь с разделом [Множественные аргументы](/docs/arguments#множественные-аргументы)._
78 |
--------------------------------------------------------------------------------
/pages/docs/data-fetching.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # 数据请求
5 |
6 | ```js
7 | const { data, error } = useSWR(key, fetcher)
8 | ```
9 |
10 | 这是 SWR 的基本 API。这里的 `fetcher` 是一个异步函数,它 **接受** SWR 的 **`key`** 并返回数据。
11 |
12 | 返回值将作为 `data` 传递,如果抛出错误,将作为 `error` 被捕获。
13 |
14 |
15 | 注意:如果 fetcher
是 全局配置提供的,可以从参数中忽略。
16 |
17 |
18 | ## Fetch [#fetch]
19 |
20 | 你可以使用任何库来处理数据请求,比如一个 `fetch` polyfill [developit/unfetch](https://github.com/developit/unfetch):
21 |
22 | ```js
23 | import fetch from 'unfetch'
24 |
25 | const fetcher = url => fetch(url).then(r => r.json())
26 |
27 | function App () {
28 | const { data, error } = useSWR('/api/data', fetcher)
29 | // ...
30 | }
31 | ```
32 |
33 |
34 | 如果你使用的是 Next.js ,则不需要引入这个 polyfill:
35 | 新的内置 Polyfills: fetch()、URL、和Object.assign
36 |
37 |
38 | ## Axios [#axios]
39 |
40 | ```js
41 | import axios from 'axios'
42 |
43 | const fetcher = url => axios.get(url).then(res => res.data)
44 |
45 | function App () {
46 | const { data, error } = useSWR('/api/data', fetcher)
47 | // ...
48 | }
49 | ```
50 |
51 | ## GraphQL [#graphql]
52 |
53 | 或者配合类似 [graphql-request](https://github.com/prisma-labs/graphql-request) 的库使用 GraphQL:
54 |
55 | ```js
56 | import { request } from 'graphql-request'
57 |
58 | const fetcher = query => request('/api/graphql', query)
59 |
60 | function App () {
61 | const { data, error } = useSWR(
62 | `{
63 | Movie(title: "Inception") {
64 | releaseDate
65 | actors {
66 | name
67 | }
68 | }
69 | }`,
70 | fetcher
71 | )
72 | // ...
73 | }
74 | ```
75 |
76 | _如果要把变量传递给 GraphQL query,请查看 [多参数](/docs/arguments)。_
77 |
--------------------------------------------------------------------------------
/pages/docs/error-handling.ja.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # エラーハンドリング
5 |
6 | もし [`fetcher`](/docs/data-fetching) 内でエラーが投げられた場合、フックは `error` として返します。
7 |
8 | ```js
9 | const fetcher = url => fetch(url).then(r => r.json())
10 |
11 | // ...
12 | const { data, error } = useSWR('/api/user', fetcher)
13 | ```
14 |
15 | フェッチの promise がリジェクトされた場合、 `error` オブジェクトが定義されます。
16 |
17 | ## ステータスコードとエラーオブジェクト [#status-code-and-error-object]
18 |
19 | しばしば、 API にステータスコードと一緒にエラーオブジェクトを返して欲しいと思うことがあります。
20 | どちらもクライアントにとっては便利なものです。
21 |
22 | `fetcher` をカスタマイズすることで、より多くの情報を返すことができます。もしステータスコードが `2xx` でない場合は、
23 | たとえ JSON としてパースできたとしても、エラーとみなします。
24 |
25 | ```js
26 | const fetcher = async url => {
27 | const res = await fetch(url)
28 |
29 | // もしステータスコードが 200-299 の範囲内では無い場合、
30 | // レスポンスをパースして投げようとします。
31 | if (!res.ok) {
32 | const error = new Error('An error occurred while fetching the data.')
33 | // エラーオブジェクトに追加情報を付与します。
34 | error.info = await res.json()
35 | error.status = res.status
36 | throw error
37 | }
38 |
39 | return res.json()
40 | }
41 |
42 | // ...
43 | const { data, error } = useSWR('/api/user', fetcher)
44 | // error.info === {
45 | // message: "You are not authorized to access this resource.",
46 | // documentation_url: "..."
47 | // }
48 | // error.status === 403
49 | ```
50 |
51 |
52 | データ
と エラー
は同時に存在することに注意してください。そのため、 UI は次のリクエストが失敗したことを知りながら、
53 | 既存のデータを表示することができます。
54 |
55 |
56 | [ここ](/examples/error-handling)ではその例を紹介しています。
57 |
58 | ## エラー時の再試行 [#error-retry]
59 |
60 | SWR は [exponential backoff アルゴリズム](https://en.wikipedia.org/wiki/Exponential_backoff) を使用して、エラー時にリクエストを再試行します。
61 | このアルゴリズムにより、アプリはエラーから素早く回復することができますが、再試行しすぎてリソースを無駄にすることはありません。
62 |
63 | また [onErrorRetry](/docs/api#options) オプションで、この動作をオーバーライドすることもできます:
64 |
65 | ```js
66 | useSWR('/api/user', fetcher, {
67 | onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
68 | // 404では再試行しない。
69 | if (error.status === 404) return
70 |
71 | // 特定のキーでは再試行しない。
72 | if (key === '/api/user') return
73 |
74 | // 再試行は10回までしかできません。
75 | if (retryCount >= 10) return
76 |
77 | // 5秒後に再試行します。
78 | setTimeout(() => revalidate({ retryCount }), 5000)
79 | }
80 | })
81 | ```
82 |
83 | このコールバックは、様々な条件にもとづいて再試行する柔軟性を提供します。 `shouldRetryOnError: false` を設定することで、この機能を無効にすることもできます。
84 |
85 | また、 [グローバルな設定](/docs/global-configuration) のコンテキストを介して提供することもできます。
86 |
87 | ## グローバルエラーの報告 [#global-error-report]
88 |
89 | コンポーネント内の `error` オブジェクトをいつでもリアクティブに取得することができます。
90 | ただし、エラーをグローバルに処理したり、 [トースト](https://vercel.com/design/toast) や [スナックバー](https://material.io/components/snackbars) を表示するように UI に通知したり、 [Sentry](https://sentry.io) などの場所で報告する場合は、
91 | [`onError`](/docs/api#options) イベントがあります:
92 |
93 | ```jsx
94 | {
96 | if (error.status !== 403 && error.status !== 404) {
97 | // エラーをSentryに送信するか、
98 | // 通知UIを表示することができます。
99 | }
100 | }
101 | }}>
102 |
103 |
104 | ```
105 |
--------------------------------------------------------------------------------
/pages/docs/error-handling.ko.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # 에러 처리
5 |
6 | [`fetcher`](/docs/data-fetching) 안에서 에러가 발생했다면 hook에 의해 `error`로 반환됩니다.
7 |
8 | ```js
9 | const fetcher = url => fetch(url).then(r => r.json())
10 |
11 | // ...
12 | const { data, error } = useSWR('/api/user', fetcher)
13 | ```
14 |
15 | fetch 프로미스가 거부되면 `error` 객체가 정의됩니다.
16 |
17 | ## 상태 코드와 에러 객체 [#status-code-and-error-object]
18 |
19 | 때로는 API가 상태 코드와 함께 에러 객체를 반환하기를 원합니다.
20 | 모두 클라이언트에게 유용합니다.
21 |
22 | `fetcher`가 더 많은 정보를 반환하도록 커스터마이징 할 수 있습니다. 상태 코드가 `2xx`이 아니라면
23 | JSON으로 파싱할 수 있더라도 이를 에러로 간주합니다.
24 |
25 | ```js
26 | const fetcher = async url => {
27 | const res = await fetch(url)
28 |
29 | // 상태 코드가 200-299 범위가 아니더라도,
30 | // 파싱 시도를 하고 에러를 던집니다.
31 | if (!res.ok) {
32 | const error = new Error('An error occurred while fetching the data.')
33 | // 에러 객체에 부가 정보를 추가합니다.
34 | error.info = await res.json()
35 | error.status = res.status
36 | throw error
37 | }
38 |
39 | return res.json()
40 | }
41 |
42 | // ...
43 | const { data, error } = useSWR('/api/user', fetcher)
44 | // error.info === {
45 | // message: "You are not authorized to access this resource.",
46 | // documentation_url: "..."
47 | // }
48 | // error.status === 403
49 | ```
50 |
51 |
52 | 데이터
와 에러
는 동시에 존재할 수 있습니다. 따라서 UI는 예정된 요청이 실패했음을 알면서도
53 | 기존 데이터를 보여줄 수 있습니다.
54 |
55 |
56 | [여기](/examples/error-handling)에 예시가 있습니다.
57 |
58 | ## 에러 재시도 [#error-retry]
59 |
60 | SWR은 [지수 백오프 알고리즘](https://en.wikipedia.org/wiki/Exponential_backoff)를 사용해 에러 시 요청을 재시도합니다.
61 | 이 알고리즘을 사용하면 에러로부터 앱을 빠르게 복구할 수 있으며 너무 자주 재시도하여 리소스를 낭비하지도 않습니다.
62 |
63 | [onErrorRetry](/docs/api#options) 옵션을 통해 이 동작을 오버라이드할 수도 있습니다.
64 |
65 | ```js
66 | useSWR('/api/user', fetcher, {
67 | onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
68 | // 404에서 재시도 안함
69 | if (error.status === 404) return
70 |
71 | // 특정 키에 대해 재시도 안함
72 | if (key === '/api/user') return
73 |
74 | // 10번까지만 재시도함
75 | if (retryCount >= 10) return
76 |
77 | // 5초 후에 재시도
78 | setTimeout(() => revalidate({ retryCount }), 5000)
79 | }
80 | })
81 | ```
82 |
83 | 이 콜백을 사용하면 다양한 조건을 기반으로 유연하게 재시도할 수 있습니다. `shouldRetryOnError: false` 설정으로 비활성화할 수도 있습니다.
84 |
85 | [전역 설정](/docs/global-configuration) 컨텍스트를 통해 제공하는 것도 가능합니다.
86 |
87 | ## 전역 에러 기록 [#global-error-report]
88 |
89 | 항상 컴포넌트 내에서 반응적으로 `error` 객체를 얻을 수 있습니다.
90 | 하지만 UI에 [토스트](https://vercel.com/design/toast) 또는 [스낵바](https://material.io/components/snackbars)를 보여주거나 [Sentry](https://sentry.io)와 같은 어딘가에 기록하기 위해 에러를 전역으로 처리하길 원할 경우,
91 | [`onError`](/docs/api#options) 이벤트가 있습니다.
92 |
93 | ```jsx
94 | {
96 | if (error.status !== 403 && error.status !== 404) {
97 | // Sentry로 에러를 보내거나,
98 | // 알림 UI를 보여줄 수 있습니다.
99 | }
100 | }
101 | }}>
102 |
103 |
104 | ```
105 |
--------------------------------------------------------------------------------
/pages/docs/error-handling.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 | import Link from 'next/link'
3 |
4 | # 错误处理
5 |
6 | 如果在 [`fetcher`](/docs/data-fetching) 中抛出错误,hook 会将其作为 `error` 返回。
7 |
8 | ```js
9 | const fetcher = url => fetch(url).then(r => r.json())
10 |
11 | // ...
12 | const { data, error } = useSWR('/api/user', fetcher)
13 | ```
14 |
15 | 如果 fetch promise 被拒绝,将定义 `error` 对象。
16 |
17 | ## 状态码和错误对象 [#status-code-and-error-object]
18 |
19 | 有时我们希望 API 在返回状态码的同时返回一个错误对象。它们对客户端都是有用的。
20 |
21 | 我们可以自定义 `fetcher` 以返回更多信息。如果状态码不是 `2xx`,我们则认为它是一个错误,即使它可以被解析为 JSON:
22 |
23 | ```js
24 | const fetcher = async url => {
25 | const res = await fetch(url)
26 |
27 | // 如果状态码不在 200-299 的范围内,
28 | // 我们仍然尝试解析并抛出它。
29 | if (!res.ok) {
30 | const error = new Error('An error occurred while fetching the data.')
31 | // 将额外的信息附加到错误对象上。
32 | error.info = await res.json()
33 | error.status = res.status
34 | throw error
35 | }
36 |
37 | return res.json()
38 | }
39 |
40 | // ...
41 | const { data, error } = useSWR('/api/user', fetcher)
42 | // error.info === {
43 | // message: "You are not authorized to access this resource.",
44 | // documentation_url: "..."
45 | // }
46 | // error.status === 403
47 | ```
48 |
49 |
50 | 注意:data
和 error
可以同时存在。所以 UI 可以在知道即将到来的请求失败时显示现有数据。
51 |
52 |
53 | [这里](/examples/error-handling)有一个示例。
54 |
55 | ## 错误重试 [#error-retry]
56 |
57 | 在出现错误时 SWR 使用[指数退避算法](https://en.wikipedia.org/wiki/Exponential_backoff)重发请求。该算法允许应用从错误中快速恢复,而不会浪费资源频繁地重试。
58 |
59 | 你还可以通过 [onErrorRetry](/docs/api#options) 选项覆盖该行为:
60 |
61 | ```js
62 | useSWR('/api/user', fetcher, {
63 | onErrorRetry: (error, key, config, revalidate, { retryCount }) => {
64 | // 404 时不重试。
65 | if (error.status === 404) return
66 |
67 | // 特定的 key 时不重试。
68 | if (key === '/api/user') return
69 |
70 | // 最多重试 10 次。
71 | if (retryCount >= 10) return
72 |
73 | // 5秒后重试。
74 | setTimeout(() => revalidate({ retryCount: retryCount }), 5000)
75 | }
76 | })
77 | ```
78 |
79 | 这个回调让你可以灵活的根据各种条件重试。你也可以通过设置 `shouldRetryOnError: false` 来禁用它。
80 |
81 | 也可以通过[全局配置](/docs/global-configuration) context 来提供它。
82 |
83 | ## 全局错误报告 [#global-error-report]
84 |
85 | 你总是可以响应性的在组件内部得到 `error` 对象。但如果你想要全局处理错误,通知 UI 显示一个 [toast](https://vercel.com/design/toast) 或者一个 [snackbar](https://material.io/components/snackbars),或在某处报告它,比如 [Sentry](https://sentry.io),可以用 [`onError`](/docs/api#options) 事件:
86 |
87 | ```jsx
88 | {
90 | if (error.status !== 403 && error.status !== 404) {
91 | // 我们可以把错误发送给 Sentry,
92 | // 或显示一个通知 UI。
93 | }
94 | }
95 | }}>
96 |
97 |
98 | ```
99 |
--------------------------------------------------------------------------------
/pages/docs/prefetching.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | # 预请求数据
2 |
3 | ## 顶级页面数据 [#top-level-page-data]
4 |
5 | 有很多方法可以为 SWR 预请求数据。对于顶级请求,强烈推荐 [`rel="preload"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content)
6 |
7 | ```html
8 |
9 | ```
10 |
11 | 只需把它放在HTML的 `` 里即可。简单、快速、原生。
12 |
13 | 它将在 HTML 加载时预请求数据,甚至是在 JavaScript 开始下载之前。使用相同 URL 的所有传入 fetch 请求都将重用结果(当然包括SWR)。
14 |
15 | ## 手动预请求 [#programmatically-prefetch]
16 |
17 | SWR 提供 `preload` API 来以编程方式预加载资源并将结果存储在缓存中。`preload` 接受 `key` 和 `fetcher` 作为参数。
18 |
19 | 你甚至可以在React之外调用 `preload`。
20 |
21 | ```jsx
22 | import { useState } from 'react'
23 | import useSWR, { preload } from 'swr'
24 |
25 | const fetcher = (url) => fetch(url).then((res) => res.json())
26 |
27 | // 在渲染下面的用户组件之前预加载资源,
28 | // 这可以防止应用程序中出现潜在的网络请求瀑布。
29 | // 您也可以在鼠标悬停在按钮或链接上时开始预加载。
30 | preload('/api/user', fetcher)
31 |
32 | function User() {
33 | const { data } = useSWR('/api/user', fetcher)
34 | ...
35 | }
36 |
37 | export default function App() {
38 | const [show, setShow] = useState(false)
39 | return (
40 |
41 | setShow(true)}>Show User
42 | {show ? : null}
43 |
44 | )
45 | }
46 | ```
47 |
48 | 在 React 渲染树中,`preload`也可以在事件处理或 effects 中使用。
49 |
50 | ```jsx
51 | function App({ userId }) {
52 | const [show, setShow] = useState(false)
53 |
54 | // 在 effects 中预加载
55 | useEffect(() => {
56 | preload('/api/user?id=' + userId, fetcher)
57 | }, [userId])
58 |
59 | return (
60 |
61 | setShow(true)}
63 | {/* 在事件回调中预加载 */}
64 | onHover={() => preload('/api/user?id=' + userId, fetcher)}
65 | >
66 | Show User
67 |
68 | {show ? : null}
69 |
70 | )
71 | }
72 | ```
73 |
74 | 配合 Next.js 的 [页面预加载](https://nextjs.org/docs/api-reference/next/router#routerprefetch),你将能立即加载下一页和数据。
75 |
76 | 在 Suspense 模式下,你应该利用`preload`来避免网络请求瀑布问题。
77 |
78 | ```jsx
79 | import useSWR, { preload } from 'swr'
80 |
81 | // 在渲染前执行
82 | preload('/api/user', fetcher);
83 | preload('/api/movies', fetcher);
84 |
85 | const Page = () => {
86 | // 下面的 useSWR 钩子会暂停渲染,但是对 `/api/user` 和 `/api/movies` 的请求已经由 `preload` 启动,
87 | // 因此不会出现网络请求瀑布。
88 | const { data: user } = useSWR('/api/user', fetcher, { suspense: true });
89 | const { data: movies } = useSWR('/api/movies', fetcher, { suspense: true });
90 | return (
91 |
92 |
93 |
94 |
95 | );
96 | }
97 | ```
98 |
99 | ## 数据预填充 [#pre-fill-data]
100 |
101 | 如果你想在 SWR 缓存中预填充已经存在的数据,你可以使用 `fallbackData` 选项,例如:
102 |
103 | ```jsx
104 | useSWR('/api/data', fetcher, { fallbackData: prefetchedData })
105 | ```
106 |
107 | 当 SWR 还没有获取此次数据的时候, 这个 hook 将返回 `prefetchedData` 作为 fallback 。
108 |
109 | 你也可以为所有的 SWR hooks 和不同的 key 配置 `` 和它的 `fallback` 选项。 查看 [Next.js SSG 和 SSR](/docs/with-nextjs) 了解更多详细信息。
110 |
--------------------------------------------------------------------------------
/pages/docs/revalidation.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import Video from 'components/video'
2 | import { Callout } from 'nextra-theme-docs'
3 | import { Bleed } from 'nextra-theme-docs'
4 | import Link from 'next/link'
5 |
6 | # 自动重新请求
7 |
8 |
9 | 如果你想手动重新请求数据,请查看 mutation。
10 |
11 |
12 | ## 聚焦时重新请求 [#revalidate-on-focus]
13 |
14 | 当你重新聚焦一个页面或在标签页之间切换时,SWR 会自动重新请求数据。
15 |
16 | 这个功能非常实用,可以保持网站同步到最新数据。对于在长时间位于后台的标签页,或 **休眠** 的电脑等情况下刷新数据也很有帮助。
17 |
18 |
19 |
25 |
26 |
27 | 该特性默认是启用的。你可以通过 [`revalidateOnFocus`](/docs/api) 选项禁用它。
28 |
29 | ## 定期重新请求 [#revalidate-on-interval]
30 |
31 | 在很多情况下,数据会因为多个设备、多个用户、多个选项卡而发生改变。那么我们如何随着时间的推移更新屏幕上的数据呢?
32 |
33 | SWR 会为你提供自动重新请求数据的选项。这很 **智能**,意味着只有与 hook 相关的组件 **在屏幕上** 时,才会重新请求。
34 |
35 |
36 |
42 |
43 |
44 | 你可以通过设置 [`refreshInterval`](/docs/api) 值来启用它:
45 |
46 | ```js
47 | useSWR('/api/todos', fetcher, { refreshInterval: 1000 })
48 | ```
49 |
50 | 还有其他选项,例如 `refreshWhenHidden` 和 `refreshWhenOffline`。这两项默认都是禁用的,所以当网页不在屏幕上或没有网络连接时,SWR 不会请求。
51 |
52 | ## 重新连接时重新请求 [#revalidate-on-reconnect]
53 |
54 | 当用户重新联机时重新请求非常有用。这种情况经常发生在用户解锁了他们的计算机但网络还没有连上时。
55 |
56 | 为了确保数据始终是最新的,SWR 会在网络恢复时自动重新请求。
57 |
58 | 该特性默认是启用的。你可以通过 [`revalidateOnReconnect`](/docs/api) 选项禁用它。
59 |
60 | ## 禁用自动重新请求 [#disable-automatic-revalidations]
61 |
62 | 如果资源是**不可变的**,即使我们再怎么重新请求也永远不会发生任何改变,那么我们可以禁用它的所有的自动重新请求。
63 |
64 | 从 1.0 版本开始,SWR 提供了一个辅助 hook `useSWRImmutable` 来标记资源为不可变的:
65 |
66 | ```js
67 | import useSWRImmutable from 'swr/immutable'
68 |
69 | // ...
70 | useSWRImmutable(key, fetcher, options)
71 | ```
72 |
73 | 它具有与普通 `useSWR` hook 相同的 API 接口。你还可以通过禁用以下重新请求选项来执行相同的操作:
74 |
75 | ```js
76 | useSWR(key, fetcher, {
77 | revalidateIfStale: false,
78 | revalidateOnFocus: false,
79 | revalidateOnReconnect: false
80 | })
81 |
82 | // 相当于
83 | useSWRImmutable(key, fetcher)
84 | ```
85 |
86 | `revalidateIfStale` 控制 SWR 在挂载并且存在陈旧数据时是否应重新请求。
87 |
88 | 上面这两个 hook 做**完全相同的**事情。一旦数据被缓存,他们将永远不会再次请求它。
89 |
90 | ## 挂载时重新请求[#revalidate-on-mount]
91 |
92 | 在组件挂载时,强制覆盖 SWR 的重新请求,这非常有用。默认情况下,`revalidateOnMount`的值为`undefined`。
93 |
94 | SWR hook 挂载过程如下:
95 |
96 | - 首先,它检查是否定义了 `revalidateOnMount`。如果为 `true`,则开始请求,如果为 `false`,则停止请求。
97 |
98 | `revalidateIfStale` 有助于控制挂载行为。默认情况下,`revalidateIfStale` 设置为 `true`。
99 |
100 | 如果 `revalidateIfStale` 设置为 `true`,则只有存在缓存数据时才会重新获取数据,否则不会重新获取。
--------------------------------------------------------------------------------
/pages/docs/subscription.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # 订阅
4 |
5 |
6 | 请升级到最新版本 (≥ 2.1.0) 来使用这个 API.
7 |
8 |
9 | ## `useSWRSubscription` [#useswrsubscription]
10 |
11 | `useSWRSubscription` 是一个使用 SWR 订阅实时数据源的 React Hook。
12 |
13 | ```tsx
14 | useSWRSubscription(key: Key, subscribe: (key: Key, options: { next: (error?: Error | null, data: Data) => void }) => () => void): { data?: Data, error?: Error }
15 | ```
16 |
17 | ### API [#api]
18 |
19 | 这个 hook 使用提供的 subscribe 函数订阅实时数据源,并返回接收到的最新数据和遇到的任何错误。当接收到新事件时,该 hook 会自动更新返回的数据。
20 |
21 | #### 参数 [#parameters]
22 |
23 | - `key`: 这是一个用于标识所订阅数据的唯一 key 值, 与 `useSWR` key 参数的用法相同。
24 | - `subscribe`: 这是一个用于订阅实时数据源的函数。它接收以下参数:
25 | - `key`: 与 `useSWRSubscription` 的 key 参数相同。
26 | - `options`: 一个带有以下属性的对象:
27 | - `next`: 一个函数,它接收一个错误和数据,然后使用从实时数据源接收到的最新数据来更新状态。
28 |
29 |
30 | 一个 subscribe 函数的例子
31 |
32 | ```tsx
33 | function subscribe(key, { next }) {
34 | const sub = remote.subscribe(key, (err, data) => next(err, data))
35 | return () => sub.close()
36 | }
37 | ```
38 |
39 | 你也可以给 `next` 函数的 `data` 参数一个函数,它接收上一次的数据作为第一个参数,然后返回一个新的数据。
40 |
41 | ```tsx
42 | function subscribe(key, { next }) {
43 | const sub = remote.subscribe(key, (err, data) => next(err, prev => prev.concat(data)))
44 | return () => sub.close()
45 | }
46 | ```
47 |
48 | #### 返回值 [#return-values]
49 |
50 | - `state`: 一个带有以下属性的对象:
51 | - `data`: 来自实时数据源的最新数据。
52 | - `error`: 如果在订阅实时数据源时发生错误,则为一个 `Error` 对象,否则为 `undefined` 。
53 |
54 | 当接收到新数据时,error 会被重置为 `undefined`。
55 |
56 | ### 基本用法 [#usage]
57 |
58 | 使用 `useSWRSubscription` 订阅 Firestore 数据源的示例代码:
59 |
60 | ```tsx
61 | import useSWRSubscription from 'swr/subscription'
62 |
63 | function Post({ id }) {
64 | const { data } = useSWRSubscription(['views', id], ([_, postId], { next }) => {
65 | const ref = firebase.database().ref('views/' + postId)
66 | ref.on('value',
67 | snapshot => next(null, snapshot.data()),
68 | err => next(err)
69 | )
70 | return () => ref.off()
71 | })
72 |
73 | return Your post has {data} views!
74 | }
75 | ```
76 |
77 | 使用 `useSWRSubscription` 订阅 WebSocket 数据源的示例代码:
78 |
79 | ```tsx
80 | import useSWRSubscription from 'swr/subscription'
81 |
82 | function App() {
83 | const { data, error } = useSWRSubscription('ws://...', (key, { next }) => {
84 | const socket = new WebSocket(key)
85 | socket.addEventListener('message', (event) => next(null, event.data))
86 | socket.addEventListener('error', (event) => next(event.error))
87 | return () => socket.close()
88 | })
89 |
90 | if (error) return failed to load
91 | if (!data) return loading...
92 | return hello {data}!
93 | }
94 | ```
95 |
96 | 你也可以在[这个页面](/docs/typescript#)查看 `useSWRSubscription` 的 TypeScript 示例。
97 |
98 | ### 去重 [#deduplication]
99 |
100 | `useSWRSubscription` 会对具有相同 `key` 的订阅请求进行去重。如果有多个组件使用相同的键,它们将共享相同的订阅。当最后一个使用该键的组件卸载时,订阅将被关闭。
101 |
102 | 这意味着如果您有多个使用相同键的组件,它们都将接收到相同的数据。并且每个 `key` 只有一个对实时数据源的订阅。
103 |
--------------------------------------------------------------------------------
/pages/docs/suspense.en-US.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | You can enable the `suspense` option to use SWR with React [Suspense](https://react.dev/reference/react/Suspense):
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | loading...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | Note that the `suspense` option is not allowed to change in the lifecycle.
27 |
28 |
29 | In Suspense mode, `data` is always the fetch response (so you don't need to check if it's `undefined`).
30 | But if an error occurred, you need to use an [error boundary](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors) to catch it:
31 |
32 | ```jsx
33 | Could not fetch posts.}>
34 | Loading posts...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | Suspense mode suspends rendering until the data is ready, which means it causes waterfall problems easily. To avoid that, you should prefetch resources before rendering. [More information](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### Note: With Conditional Fetching [#note-with-conditional-fetching]
47 |
48 | Normally, when you enabled `suspense` it's guaranteed that `data` will always be ready on render:
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data` will never be `undefined`
55 | // ...
56 | }
57 | ```
58 |
59 | However, when using it together with conditional fetching or dependent fetching, `data` will be `undefined` if the request is **paused**:
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `data` will be `undefined` if `isReady` is false
66 | // ...
67 | }
68 | ```
69 |
70 | If you want to read more technical details about this restriction, check [the discussion here](https://github.com/vercel/swr/pull/357#issuecomment-627089889).
71 |
72 | ### Server-Side Rendering [#server-side-rendering]
73 |
74 | When using suspense mode on the server-side (including pre-rendering in Next.js), it's **required** to provide the initial data via [fallbackData or fallback](/docs/with-nextjs#pre-rendering-with-default-data). This means that you can't use `Suspense` to fetch data on the server side, but either doing fully client-side data fetching, or fetch the data via the framework level data fetching method(such as getStaticProps in Next.js). More discussions can be found [here](https://github.com/vercel/swr/issues/1906).
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.es-ES.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | Puede activar la opción `suspense` para utilizar SWR con React [Suspense](https://react.dev/reference/react/Suspense):
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | loading...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | Tenga en cuenta que la opción `suspense` no puede cambiar en el ciclo de vida.
27 |
28 |
29 | En el modo Suspense, `data` es siempre la respuesta fetch (por lo que no es necesario comprobar si es `undefined`).
30 | Pero si se produce un error, es necesario utilizar un [error boundary](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors) para atraparlo:
31 |
32 | ```jsx
33 | Could not fetch posts.}>
34 | Loading posts...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | Suspense mode suspends rendering until the data is ready, which means it causes waterfall problems easily. To avoid that, you should prefetch resources before rendering. [More information](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### Note: With Conditional Fetching [#note-with-conditional-fetching]
47 |
48 | Normalmente, cuando se habilita `suspense` se garantiza que `data` siempre estarán lista al renderizar:
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data` nunca sera `undefined`
55 | // ...
56 | }
57 | ```
58 |
59 | Sin embargo, cuando se utiliza junto con el conditional fetching o dependent fetching, `data` estará `undefined` si la solicitud está **paused**:
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `data` será `undefined` si `isReady` es false
66 | // ...
67 | }
68 | ```
69 |
70 | Si quiere leer más detalles técnicos sobre esta restricción, consulte [la discusión aquí](https://github.com/vercel/swr/pull/357#issuecomment-627089889).
71 |
72 | ### Server-Side Rendering [#server-side-rendering]
73 |
74 | When using suspense mode on the server-side (including pre-rendering in Next.js), it's **required** to provide the initial data via [fallbackData or fallback](/docs/with-nextjs#pre-rendering-with-default-data). This means that you can't use `Suspense` to fetch data on the server side, but either doing fully client-side data fetching, or fetch the data via the framework level data fetching method(such as getStaticProps in Next.js). More discussions can be found [here](https://github.com/vercel/swr/issues/1906).
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | Vous pouvez activer l'option `suspense` pour utiliser SWR avec React [Suspense](https://react.dev/reference/react/Suspense):
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return bonjour, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | chargement...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | Notez que l'option `suspense` n'est pas autorisée à changer dans le cycle de vie.
27 |
28 |
29 | En mode Suspense, `data` est toujours la réponse de la requête (vous n'avez donc pas besoin de vérifier si elle est `undefined`).
30 | Mais si une erreur s'est produite, vous devez utiliser une [limite d'erreur](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors) pour la capturer :
31 |
32 | ```jsx
33 | Impossible de récupérer les messages}>
34 | Chargements des messages...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | Le mode Suspense suspend le rendu jusqu'à ce que les données soient prêtes, ce qui signifie qu'il provoque facilement des problèmes de cascade. Pour éviter cela, vous devez précharger les ressources avant le rendu. [Plus d'informations](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### Note: Avec le rendu conditionnel [#note-with-conditional-rendering]
47 |
48 | Normalement, lorsque vous activez `suspense`, il est garanti que `data` sera toujours prêt au rendu :
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data` ne sera jamais `undefined`
55 | // ...
56 | }
57 | ```
58 |
59 | Cependant, lorsqu'il est utilisé avec le chargement conditionnel ou le chargement dépendant, `data` sera `undefined` si la requête est **en pause** :
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `data` sera `undefined` si `isReady` est false
66 | // ...
67 | }
68 | ```
69 |
70 | Si vous voulez lire plus de détails techniques sur cette restriction, consultez [la discussion ici](https://github.com/vercel/swr/pull/357#issuecomment-627089889).
71 |
72 | ### Rendu côté serveur [#server-side-rendering]
73 |
74 | Lorsque vous utilisez le mode suspense côté serveur (y compris le pré-rendu dans Next.js), il est **obligatoire** de fournir les données initiales via [fallbackData ou fallback](/docs/with-nextjs#pre-rendering-with-default-data). Cela signifie que vous ne pouvez pas utiliser `Suspense` pour récupérer des données côté serveur, mais que vous devez soit effectuer une récupération de données entièrement côté client, soit récupérer les données via la méthode de récupération de données de niveau framework (comme getStaticProps dans Next.js). Vous trouverez plus de discussions [ici](https://github.com/vercel/swr/issues/1906).
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.ja.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | React [サスペンスで](https://react.dev/reference/react/Suspense) SWR を使用するには、 `suspense` オプションを有効にします。
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | loading...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | `suspense` オプションは、ライフサイクル内では変更できないことに注意してください。
27 |
28 |
29 | サスペンスモードでの `data` は常にフェッチのレスポンスです(よって `undefined` かどうかをチェックする必要はありません)。
30 | ただし、エラーが発生した場合は、エラーをキャッチするために[エラーバウンダリー](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors)を使う必要があります:
31 |
32 | ```jsx
33 | Could not fetch posts.}>
34 | Loading posts...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | サスペンスモードはデータが利用可能になるまでレンダリングを中断します。これは簡単にウォーターフォール問題を引き起こすことを意味します。これを避けるためにはレンダリングの前にリソースをプリフェッチする必要があります。[詳細はこちら](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### 注:条件付きフェッチを使用する場合 [#note-with-conditional-fetching]
47 |
48 | 通常、`suspense` を有効にすると、レンダリング時に `data` が常に準備ができていることが保証されます:
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data` は決して `undefined` にはなりません
55 | // ...
56 | }
57 | ```
58 |
59 | ただし、条件付きフェッチまたは依存フェッチと一緒に使用すると、リクエストが**一時停止**された場合に `data` は `undefined` なります:
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `isReady` が false のときには `data` は `undefined` になります
66 | // ...
67 | }
68 | ```
69 |
70 | この制限に関する技術的な詳細を読みたい場合は、[こちらの議論](https://github.com/vercel/swr/pull/357#issuecomment-627089889)を確認してください。
71 |
72 | ### サーバサイドレンダリング [#server-side-rendering]
73 |
74 | サスペンスモードをサーバサイド(Next.js によるプリレンダリングを含む)で使う場合、[fallbackData や fallback](/docs/with-nextjs#pre-rendering-with-default-data) により初期データが提供されている**必要があります**。これはサスペンスをサーバサイドでのデータ取得に使うことができないことを意味しており、クライアントサイドでのデータ取得を行うか、フレームワークを通じたデータ取得(Next.js の getStaticProps のような)のどちらかを行う必要があります。これについての議論は[こちら](https://github.com/vercel/swr/issues/1906)です。
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.ko.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | React [서스펜스를](https://react.dev/reference/react/Suspense) SWR과 함께 사용하려면 `suspense` 옵션을 활성화하세요.
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | loading...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | `suspense` 옵션은 생명 주기 내에서 변경을 허용하지 않습니다.
27 |
28 |
29 | 서스펜스 모드에서 `data`는 항상 응답을 가져옵니다(따라서 `undefined`를 검사할 필요가 없습니다).
30 | 하지만 에러가 발생할 경우 [에러 경계](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors)를 사용해 캐치해야 합니다.
31 |
32 | ```jsx
33 | Could not fetch posts.}>
34 | Loading posts...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | Suspense mode suspends rendering until the data is ready, which means it causes waterfall problems easily. To avoid that, you should prefetch resources before rendering. [More information](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### 노트: 조건부 가져오기와 함께 [#note-with-conditional-fetching]
47 |
48 | 일반적으로 `suspense`를 활성화하면 렌더링 시에 `data`가 항상 준비됩니다.
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data`는 절대 `undefined`가 되지 않습니다
55 | // ...
56 | }
57 | ```
58 |
59 | 하지만 조건부 가져오기나 의존적 가져오기와 함께 사용되면 `data`는 요청이 **일시 중단**된 경우 `undefined`가 됩니다.
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `isReady`가 false이면 `data`는 `undefined`입니다
66 | // ...
67 | }
68 | ```
69 |
70 | 이 제한에 대한 더 기술적인 상세 내용을 읽으려면 [여기를](https://github.com/vercel/swr/pull/357#issuecomment-627089889) 확인해 보세요.
71 |
72 | ### 서버 사이드 렌더링 [#server-side-rendering]
73 |
74 | 서스펜스 모드를 서버 사이드에서 사용할 때 (Next.js에서의 pre-rendering 포함), [fallbackData 또는 fallback](/docs/with-nextjs#pre-rendering-with-default-data)을 통해 초기 데이터를 **제공해야만 합니다**. 즉, 서버 사이드에서`Suspense`를 사용 할 수 없지만, 클라이언트 측 데이터 불러오기나, 프레임워크 수준의 데이터 불러오기(Next.js의 getStaticProps 등)는 가능합니다. 더 많은 정보는 [여기서](https://github.com/vercel/swr/issues/1906) 찾아보세요.
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | Você pode habilitar a opção `suspense` para usar SWR com React [Suspense](https://react.dev/reference/react/Suspense):
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | carregando...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | Note que a opção `suspense` não é permitida a mudar no ciclo de vida.
27 |
28 |
29 | Em modo Suspense, `data` é sempre a resposta do fetch (então você não precisa checar se é `undefined`).
30 | Mas se um erro ocorreu, você precisa usar um [limite de erro (Error Boundary)](https://pt-br.reactjs.org/docs/error-boundaries.html) para o capturar:
31 |
32 | ```jsx
33 | Não foi possível obter posts.}>
34 | Carregando posts...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | O modo Suspense suspende a renderização até que os dados estejam prontos, o que significa que pode causar problemas de waterfall facilmente. Para evitar isso, você deve fazer prefetch de recursos antes de renderizar. [Mais informações](/docs/prefetching)
42 |
43 |
44 | ### Nota: Com Fetching Condicional [#note-with-conditional-fetching]
45 |
46 | Normalmente, quando você habilita `suspense`, é garantido que `data` estará sempre pronto na renderização:
47 |
48 | ```jsx
49 | function Profile () {
50 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
51 |
52 | // `data` nunca será `undefined`
53 | // ...
54 | }
55 | ```
56 |
57 | No entanto, ao usá-lo junto com uma busca condicional ou busca dependente, `data` será `undefined` se a solicitação estiver **pausada**:
58 |
59 | ```jsx
60 | function Profile () {
61 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
62 |
63 | // `data` será `undefined` se `isReady` é false
64 | // ...
65 | }
66 | ```
67 |
68 | Se você quiser ler mais detalhes técnicos sobre essa restrição, cheque [a discussão aqui](https://github.com/vercel/swr/pull/357#issuecomment-627089889).
69 |
70 | ### Server-Side Rendering [#server-side-rendering]
71 |
72 | Quando usando o modo Suspense no lado do servidor (incluindo pre-rendering com Next.js), é **obrigatório** informar dados iniciais via [fallbackData ou fallback](/docs/with-nextjs#pre-rendering-with-default-data). Isso significa que você não pode usar `Suspense` para obter dados no lado do servidor, mas fazendo a busca de dados totalmente do lado do cliente ou buscando os dados por meio do método de busca de dados à nível de framework (como getStaticProps com Next.js). Mais discussões podem ser enconrtradas [aqui](https://github.com/vercel/swr/issues/1906).
73 |
--------------------------------------------------------------------------------
/pages/docs/suspense.ru.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | Вы можете включить опцию `suspense`, чтобы использовать SWR с React [Suspense](https://react.dev/reference/react/Suspense):
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return привет, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | загрузка...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | Обратите внимание, что опцию `suspense` нельзя изменять в жизненном цикле.
27 |
28 |
29 | В режиме задержки `data` всегда является ответом выборки (поэтому вам не нужно проверять, является ли она `undefined`).
30 | Но если произошла ошибка, вам нужно использовать [предохранители](https://ru.reactjs.org/docs/concurrent-mode-suspense.html#handling-errors), чтобы её отловить:
31 |
32 | ```jsx
33 | Не удалось получить посты.}>
34 | Загрузка постов...}>
35 |
36 |
37 |
38 | ```
39 |
40 |
41 | Режим Suspense приостанавливает рендеринг до тех пор, пока данные не будут готовы, что означает, что он легко вызывает проблемы водопада. Чтобы избежать этого, вы должны делать предвыборку ресурсов перед рендерингом. [Дополнительная информация](/docs/prefetching)
42 |
43 |
44 | ---
45 |
46 | ### Примечание: используя условную выборку [#note-with-conditional-fetching]
47 |
48 | Обычно, когда вы включаете `suspense`, гарантируется, что `data` всегда будет готова к рендерингу:
49 |
50 | ```jsx
51 | function Profile () {
52 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
53 |
54 | // `data` никогда не будет `undefined`
55 | // ...
56 | }
57 | ```
58 |
59 | Однако при её использовании вместе с условной выборкой или зависимой выборкой — `data` будет `undefined`, если запрос **приостановлен**:
60 |
61 | ```jsx
62 | function Profile () {
63 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
64 |
65 | // `data` будет `undefined` если `isReady` имеет значение false
66 | // ...
67 | }
68 | ```
69 |
70 | Если вы хотите узнать больше технических подробностей об этом ограничении, смотрите [обсуждения здесь](https://github.com/vercel/swr/pull/357#issuecomment-627089889).
71 |
72 | ### Серверный рендеринг (SSR) [#server-side-rendering]
73 |
74 | При использовании режима задержки на сервере (включая предварительный рендеринг в Next.js) **требуется** предоставить исходные данные через [fallbackData или fallback](/docs/with-nextjs#предварительный-рендеринг-с-исходными-данными). Это означает, что вы не можете использовать `Suspense` для получения данных на сервере, а либо полностью извлекаете данные на стороне клиента, либо извлекаете данные с помощью метода извлечения данных на уровне фреймворка (например, getStaticProps в Next.js). Больше обсуждений можно найти [здесь](https://github.com/vercel/swr/issues/1906).
75 |
--------------------------------------------------------------------------------
/pages/docs/suspense.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | import { Callout } from 'nextra-theme-docs'
2 |
3 | # Suspense
4 |
5 | 你可以启用 `suspense` 选项,从而让 SWR 和 React [Suspense](https://react.dev/reference/react/Suspense) 一起使用:
6 |
7 | ```jsx
8 | import { Suspense } from 'react'
9 | import useSWR from 'swr'
10 |
11 | function Profile () {
12 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
13 | return hello, {data.name}
14 | }
15 |
16 | function App () {
17 | return (
18 | loading...}>
19 |
20 |
21 | )
22 | }
23 | ```
24 |
25 |
26 | 请注意,SWR 的 `suspense` 选项并不支持在渲染过程中发生改变。
27 |
28 |
29 | 在 Suspense 模式下,`data` 总是请求响应(因此你无需检查它是否是 `undefined`)。但如果发生错误,则需要使用 [错误边界](https://reactjs.org/docs/concurrent-mode-suspense.html#handling-errors) 来捕获它:
30 |
31 | ```jsx
32 | Could not fetch posts.}>
33 | Loading posts...}>
34 |
35 |
36 |
37 | ```
38 |
39 |
40 | Suspense 模式会在数据准备就绪前暂停渲染,这意味着它很容易导致请求瀑布问题。为了避免这种情况,应该在渲染之前预请求获取资源。[更多信息](/docs/prefetching)
41 |
42 |
43 | ---
44 |
45 | ### 注意:使用条件请求 [#note-with-conditional-fetching]
46 |
47 | 通常,当启用 `suspense` 时,可以确保 `data` 在渲染时始终是准备就绪的:
48 |
49 | ```jsx
50 | function Profile () {
51 | const { data } = useSWR('/api/user', fetcher, { suspense: true })
52 |
53 | // `data` 永远不会是 `undefined`
54 | // ...
55 | }
56 | ```
57 |
58 | 但是,当它与条件请求或依赖请求一起使用时,如果请求被**暂停**,`data` 将会是 `undefined`:
59 |
60 | ```jsx
61 | function Profile () {
62 | const { data } = useSWR(isReady ? '/api/user' : null, fetcher, { suspense: true })
63 |
64 | // 如果 `isReady` 是 false,`data` 将会是 `undefined`
65 | // ...
66 | }
67 | ```
68 |
69 | 如果你想阅读有关该限制的更多技术细节,请查看[这里的讨论](https://github.com/vercel/swr/pull/357#issuecomment-627089889)。
70 |
71 | ### 服务端渲染 [#server-side-rendering]
72 |
73 | 当在服务端渲染(包括 Next.js 中的预渲染功能)中使用 suspense 模式时,**必须**通过 [fallbackData 或 fallback](/docs/with-nextjs#pre-rendering-with-default-data) 提供初始数据,这意味着你不能使用 `Suspense` 在服务器端获取数据,而是完全使用客户端的数据请求,或者通过框架级的数据获取方法(例如 Next.js 中的 getStaticProps)获取数据,更多的讨论可以在[这里](https://github.com/vercel/swr/issues/1906)找到。
--------------------------------------------------------------------------------
/pages/examples/_meta.en-US.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "Basic Usage",
3 | "auth": "Authentication",
4 | "optimistic-ui": "Optimistic UI",
5 | "infinite-loading": "Infinite Loading",
6 | "error-handling": "Error Handling",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Subscription"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.es-ES.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "Uso Básico",
3 | "auth": "Autenticación",
4 | "infinite-loading": "Carga Infinita",
5 | "error-handling": "Manejo De Errores",
6 | "ssr": "Next.js SSR",
7 | "subscription": "Subscription"
8 | }
9 |
--------------------------------------------------------------------------------
/pages/examples/_meta.fr-FR.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "Utilisation de Base",
3 | "auth": "Authentification",
4 | "optimistic-ui": "UI Optimiste",
5 | "infinite-loading": "Chargement Infini",
6 | "error-handling": "Gestion des Erreurs",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Abonnement"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "基本的な使用法",
3 | "auth": "認証",
4 | "optimistic-ui": "楽観的なUI",
5 | "infinite-loading": "無限ローディング",
6 | "error-handling": "エラーハンドリング",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Subscription"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "기본 사용법",
3 | "auth": "인증",
4 | "optimistic-ui": "옵티미스틱 UI",
5 | "infinite-loading": "인피니트 로딩",
6 | "error-handling": "에러 처리",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Subscription"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.pt-BR.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "Uso Básico",
3 | "auth": "Autenticação",
4 | "optimistic-ui": "UI Otimista",
5 | "infinite-loading": "Carregamento Infinito",
6 | "error-handling": "Manipulação de Erros",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Subscription"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "Основное использование",
3 | "auth": "Аутентификация",
4 | "optimistic-ui": "Оптимистичный UI",
5 | "infinite-loading": "Бесконечная загрузка",
6 | "error-handling": "Обработка ошибок",
7 | "ssr": "Next.js SSR",
8 | "subscription": "Subscription"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/_meta.zh-CN.json:
--------------------------------------------------------------------------------
1 | {
2 | "basic": "基本用法",
3 | "auth": "身份验证",
4 | "optimistic-ui": "Optimistic UI",
5 | "infinite-loading": "无限加载",
6 | "error-handling": "错误处理",
7 | "ssr": "Next.js SSR",
8 | "subscription": "订阅"
9 | }
10 |
--------------------------------------------------------------------------------
/pages/examples/auth.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Authentication
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Autenticación
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Authentification
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 認証
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 인증
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Autenticação
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Аутентификация
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/auth.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 身份验证
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Basic Usage
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Uso Básico
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Utilisation Basique
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 基本的な使用法
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 기본 사용법
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Uso Básico
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Основное использование
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/basic.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 基本用法
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Error Handling
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Manejo De Errores
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Gestion des erreurs
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: エラーハンドリング
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 에러 처리
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Manipulação de Erros
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Обработка ошибок
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/error-handling.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 错误处理
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Infinite Loading
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Carga Infinita
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Chargement Infini
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 無限ローディング
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 인피니트 로딩
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Carregamento Infinito
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Бесконечная загрузка
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/infinite-loading.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 无限加载
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Optimistic UI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Optimistic UI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: UI Optimiste
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 楽観的なUI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 옵티미스틱 UI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: UI Otimista
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Оптимистичный UI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/optimistic-ui.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Optimistic UI
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/ssr.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Next.js SSR
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.en-US.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.es-ES.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.fr-FR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Abonnement
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.pt-BR.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.ru.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/examples/subscription.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Subscription
3 | full: true
4 | ---
5 |
6 |
19 |
--------------------------------------------------------------------------------
/pages/index.ja.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: データ取得のための React Hooks ライブラリ
3 | ---
4 |
5 | import { Callout } from 'nextra-theme-docs'
6 | import Features from 'components/features'
7 | import { Bleed } from 'nextra-theme-docs'
8 |
9 | {
10 | // wrapped with {} to mark it as javascript so mdx will not put it under a p tag
11 | }
12 | {SWR }
13 |
14 |
15 |
16 |
17 |
18 | “SWR” という名前は、 [HTTP RFC 5861](https://tools.ietf.org/html/rfc5861) で提唱された HTTP キャッシュ無効化戦略である `stale-while-revalidate` に由来しています。
19 | SWR は、まずキャッシュからデータを返し(stale)、次にフェッチリクエストを送り(revalidate)、最後に最新のデータを持ってくるという戦略です。
20 |
21 |
22 | SWR では、 コンポーネントはデータの更新を継続的 かつ自動的 に受け取ることができます。
23 | そして、 UI は常に高速 でリアクティブ なモノになります。
24 |
25 |
26 |
27 | [はじめに](/docs/getting-started) · [例題](/examples/basic) · [ブログ](/blog) · [GitHub リポジトリ](https://github.com/vercel/swr)
28 |
29 |
30 | ## 概要 [#overview]
31 |
32 | ```jsx
33 | import useSWR from 'swr'
34 |
35 | function Profile() {
36 | const { data, error, isLoading } = useSWR('/api/user', fetcher)
37 |
38 | if (error) return failed to load
39 | if (isLoading) return loading...
40 | return hello {data.name}!
41 | }
42 | ```
43 |
44 | この例では、`useSWR` フックは `key` 文字列と `fetcher` 関数を受け取ります。 `key` はデータの一意な識別子(通常は API の URL)で、`fetcher` に渡されます。
45 | `fetcher` はデータを返す任意の非同期関数で、ネイティブの fetch や Axios のようなツールを使うことができます。
46 |
47 | このフックは、リクエストの状態にもとづいて `data` と `isLoading`, `error` の三つの値を返します。
48 |
49 | ## 特徴 [#features]
50 |
51 | たった 1 行のコードで、プロジェクト内のデータ取得のロジックを単純化し、さらにこれらの素晴らしい機能をすぐに利用できるようになります:
52 |
53 | - **速い**、 **軽量** そして **再利用可能** なデータの取得
54 | - 組み込みの **キャッシュ** とリクエストの重複排除
55 | - **リアルタイム** な体験
56 | - トランスポートとプロトコルにとらわれない
57 | - SSR / ISR / SSG support
58 | - TypeScript 対応
59 | - React Native
60 |
61 | SWR は、スピード、正確性、安定性のすべての面をカバーし、より良い体験を構築するのに役立ちます:
62 |
63 | - 高速なページナビゲーション
64 | - 定期的にポーリングする
65 | - データの依存関係
66 | - フォーカス時の再検証
67 | - ネットワーク回復時の再検証
68 | - ローカルキャッシュの更新(Optimistic UI)
69 | - スマートなエラーの再試行
70 | - ページネーションとスクロールポジションの回復
71 | - React Suspense
72 |
73 | And lot [more](/docs/getting-started).
74 |
75 | ## コミュニティ [#community]
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | SWR は、React フレームワークである [Next.js](https://nextjs.org) と同じチームによって作られています。
84 | 今後のプロジェクトのアップデートについては、Twitter で [@vercel](https://twitter.com/vercel) をフォローしてください。
85 |
86 | お気軽に [GitHub のディスカッション](https://github.com/vercel/swr/discussions) に参加してください!
87 |
--------------------------------------------------------------------------------
/pages/index.ko.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 데이터 가져오기를 위한 React Hooks
3 | ---
4 |
5 | import { Callout } from 'nextra-theme-docs'
6 | import Features from 'components/features'
7 | import { Bleed } from 'nextra-theme-docs'
8 |
9 | {
10 | // wrapped with {} to mark it as javascript so mdx will not put it under a p tag
11 | }
12 | {SWR }
13 |
14 |
15 |
16 | "SWR"이라는 이름은 [HTTP RFC 5861](https://tools.ietf.org/html/rfc5861)에 의해 알려진 HTTP 캐시 무효 전략인 `stale-while-revalidate`에서 유래되었습니다.
17 | SWR은 먼저 캐시(stale)로부터 데이터를 반환한 후, fetch 요청(revalidate)을 하고, 최종적으로 최신화된 데이터를 가져오는 전략입니다.
18 |
19 |
20 | SWR을 사용하면 컴포넌트는 지속적 이며 자동으로 데이터 업데이트 스트림을 받게 됩니다.
21 | 그리고 UI는 항상 빠르고 반응적 입니다.
22 |
23 |
24 |
25 | [시작하기](/docs/getting-started) · [예시](/examples/basic) · [블로그](/blog) · [GitHub 리포지터리](https://github.com/vercel/swr)
26 |
27 |
28 | ## 개요 [#overview]
29 |
30 | ```jsx
31 | import useSWR from 'swr'
32 |
33 | function Profile() {
34 | const { data, error, isLoading } = useSWR('/api/user', fetcher)
35 |
36 | if (error) return failed to load
37 | if (isLoading) return loading...
38 | return hello {data.name}!
39 | }
40 | ```
41 |
42 | 이 예시에서, `useSWR` hook은 `key` 문자열과 `fetcher` 함수를 받습니다. `key`는 데이터의 고유한 식별자이며(일반적으로 API URL)
43 | `fetcher`로 전달될 것입니다. `fetcher`는 데이터를 반환하는 어떠한 비동기 함수도 될 수 있습니다. 네이티브 fetch 또는 Axios와 같은 도구를 사용할 수 있습니다.
44 |
45 | hook은 세 개의 값을 반환합니다: 요청의 상태에 기반한 `data`, `isLoading` 그리고 `error`.
46 |
47 | ## 기능 [#features]
48 |
49 | 단 한 줄의 코드로 프로젝트 내의 데이터 가져오기 로직을 단순화할 수 있으며, 다음과 같은 모든 놀라운 기능들을 바로 사용할 수도 있습니다.
50 |
51 | - **빠르고**, **가볍고**, **재사용 가능한** 데이터 가져오기
52 | - 내장된 **캐시** 및 요청 중복 제거
53 | - **실시간** 경험
54 | - 전송 및 프로토콜에 구애받지 않음
55 | - SSR / ISR / SSG 지원
56 | - TypeScript 지원
57 | - React Native
58 |
59 | SWR은 더 나은 경험을 구축할 수 있도록 속도, 정확성, 안정성의 모든 측면을 다룹니다.
60 |
61 | - 빠른 페이지 네비게이션
62 | - 인터벌 폴링
63 | - 데이터 의존성
64 | - 포커스시 재검증
65 | - 네트워크 회복시 재검증
66 | - 로컬 뮤테이션(Optimistic UI)
67 | - 스마트한 에러 재시도
68 | - 페이지 및 스크롤 위치 복구
69 | - React Suspense
70 |
71 | 그리고 [더 많이](/docs/getting-started) 있습니다.
72 |
73 | ## 커뮤니티 [#community]
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | SWR은 React 프레임워크인 [Next.js](https://nextjs.org)를 만든 동일한 팀이 만들었습니다.
82 | 앞으로의 프로젝트 업데이트를 위해 Twitter에서 [@vercel](https://twitter.com/vercel)을 팔로우해주세요.
83 |
84 | 언제라도 편하게 [GitHub discussions](https://github.com/vercel/swr/discussions)에 참여해주세요!
85 |
--------------------------------------------------------------------------------
/pages/index.zh-CN.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 用于数据请求的 React Hooks 库
3 | ---
4 |
5 | import { Callout } from 'nextra-theme-docs'
6 | import Features from "components/features"
7 | import { Bleed } from 'nextra-theme-docs'
8 |
9 | {
10 | // wrapped with {} to mark it as javascript so mdx will not put it under a p tag
11 | }
12 | {SWR }
13 |
14 |
15 |
16 |
17 |
18 | “SWR” 这个名字来自于 `stale-while-revalidate`:一种由 [HTTP RFC 5861](https://tools.ietf.org/html/rfc5861) 推广的 HTTP 缓存失效策略。这种策略首先从缓存中返回数据(过期的),同时发送 fetch 请求(重新验证),最后得到最新数据。
19 |
20 |
21 | 使用 SWR,组件将会不断地 、自动 获得最新数据流。
22 | UI 也会一直保持快速响应 。
23 |
24 |
25 |
26 | [入门](/docs/getting-started) · [示例](/examples/basic) · [博客](/blog) · [GitHub 仓库](https://github.com/vercel/swr)
27 |
28 |
29 | ## 概览 [#overview]
30 |
31 | ```jsx
32 | import useSWR from 'swr'
33 |
34 | function Profile() {
35 | const { data, error, isLoading } = useSWR('/api/user', fetcher)
36 |
37 | if (error) return failed to load
38 | if (isLoading) return loading...
39 | return hello {data.name}!
40 | }
41 | ```
42 |
43 | 该示例中,`useSWR` hook 接受一个字符串 `key` 和一个函数 `fetcher`。`key` 是数据的唯一标识符(通常是 API URL),并传递给 `fetcher`。`fetcher` 可以是任何返回数据的异步函数,你可以使用原生的 fetch 或 Axios 之类的工具。
44 |
45 | 基于请求的状态,这个 hook 返回 2 个值:`data` 和 `error`。
46 |
47 | ## 特性 [#features]
48 |
49 | 仅需一行代码,你就可以简化项目中数据请求的逻辑,并立即拥有以下这些不可思议的特性:
50 |
51 | - **极速**、**轻量**、**可重用的** 数据请求
52 | - 内置 **缓存** 和重复请求去除
53 | - **实时** 体验
54 | - 传输和协议不可知
55 | - 支持 SSR / ISR / SSG
56 | - 支持 TypeScript
57 | - React Native
58 |
59 | SWR 涵盖了性能,正确性和稳定性的各个方面,以帮你建立更好的体验:
60 |
61 | - 快速页面导航
62 | - 间隔轮询
63 | - 数据依赖
64 | - 聚焦时重新验证
65 | - 网络恢复时重新验证
66 | - 本地缓存更新 (Optimistic UI)
67 | - 智能错误重试
68 | - 分页和滚动位置恢复
69 | - React Suspense
70 |
71 | 以及 [更多](/docs/getting-started)。
72 |
73 | ## 社区 [#community]
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | SWR 由 [Next.js](https://nextjs.org)(React 框架)背后的同一团队创建。
82 | 在 Twitter 上关注 [@vercel](https://twitter.com/vercel) 未来项目更新
83 |
84 | 欢迎加入 [GitHub 上的讨论](https://github.com/vercel/swr/discussions)!
85 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/public/favicon/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/favicon/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/android-chrome-512x512.png
--------------------------------------------------------------------------------
/public/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #ffffff
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/public/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/favicon.ico
--------------------------------------------------------------------------------
/public/favicon/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/favicon/mstile-150x150.png
--------------------------------------------------------------------------------
/public/favicon/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "SWR",
3 | "short_name": "SWR",
4 | "start_url": "/",
5 | "icons": [
6 | {
7 | "src": "/favicon/android-chrome-192x192.png",
8 | "sizes": "192x192",
9 | "type": "image/png"
10 | },
11 | {
12 | "src": "/favicon/android-chrome-512x512.png",
13 | "sizes": "512x512",
14 | "type": "image/png"
15 | }
16 | ],
17 | "theme_color": "#ffffff",
18 | "background_color": "#ffffff",
19 | "display": "standalone"
20 | }
21 |
--------------------------------------------------------------------------------
/public/img/devtools/cache-view.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/img/devtools/cache-view.jpg
--------------------------------------------------------------------------------
/public/img/understanding/isloading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/img/understanding/isloading.gif
--------------------------------------------------------------------------------
/public/video/optimistic-ui.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vercel/swr-site/c18a9d0925e745b60cefe82e66e744aa6923c613/public/video/optimistic-ui.mp4
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | @tailwind utilities;
2 |
3 | html {
4 | font-feature-settings: "rlig" 1, "calt" 1, "ss01" 1, "ss06" 1 !important;
5 | }
6 |
7 | [data-reach-skip-link] {
8 | @apply sr-only;
9 | }
10 |
11 | [data-reach-skip-link]:focus {
12 | @apply not-sr-only fixed ml-6 top-0 bg-white text-lg px-6 py-2 mt-2 outline-none focus:ring z-50;
13 | }
14 |
15 | .dark .invert-on-dark {
16 | filter: invert(1) brightness(1.8);
17 | }
18 |
19 | body {
20 | background: linear-gradient(
21 | to bottom,
22 | rgba(255, 255, 255, 0) 0%,
23 | rgba(255, 255, 255, 1) 300px
24 | ),
25 | fixed 0 0 / 20px 20px radial-gradient(#d1d1d1 1px, transparent 0),
26 | fixed 10px 10px / 20px 20px radial-gradient(#d1d1d1 1px, transparent 0);
27 | }
28 |
29 | .dark body {
30 | background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, #111 300px),
31 | fixed 0 0 / 20px 20px radial-gradient(#313131 1px, transparent 0),
32 | fixed 10px 10px / 20px 20px radial-gradient(#313131 1px, transparent 0);
33 | }
34 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: [
3 | "./components/**/*.js",
4 | "./pages/**/*.{md,mdx}",
5 | "./theme.config.js",
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------