From 9ff3ab2be6640d1b34450f828761f2b943e097d1 Mon Sep 17 00:00:00 2001 From: suhaotian Date: Wed, 20 Mar 2024 09:46:09 +1100 Subject: [PATCH] chore(example): add xior and xior-typescript example --- examples/xior-typescript/README.md | 30 +++++++++ examples/xior-typescript/libs/useRequest.ts | 66 +++++++++++++++++++ examples/xior-typescript/next-env.d.ts | 5 ++ examples/xior-typescript/package.json | 23 +++++++ .../xior-typescript/pages/[user]/[repo].tsx | 34 ++++++++++ examples/xior-typescript/pages/api/data.ts | 28 ++++++++ examples/xior-typescript/pages/index.tsx | 26 ++++++++ examples/xior-typescript/tsconfig.json | 29 ++++++++ examples/xior/README.md | 30 +++++++++ examples/xior/libs/useRequest.js | 18 +++++ examples/xior/package.json | 18 +++++ examples/xior/pages/[user]/[repo].js | 38 +++++++++++ examples/xior/pages/api/data.js | 22 +++++++ examples/xior/pages/index.js | 26 ++++++++ 14 files changed, 393 insertions(+) create mode 100644 examples/xior-typescript/README.md create mode 100644 examples/xior-typescript/libs/useRequest.ts create mode 100644 examples/xior-typescript/next-env.d.ts create mode 100644 examples/xior-typescript/package.json create mode 100644 examples/xior-typescript/pages/[user]/[repo].tsx create mode 100644 examples/xior-typescript/pages/api/data.ts create mode 100644 examples/xior-typescript/pages/index.tsx create mode 100644 examples/xior-typescript/tsconfig.json create mode 100644 examples/xior/README.md create mode 100644 examples/xior/libs/useRequest.js create mode 100644 examples/xior/package.json create mode 100644 examples/xior/pages/[user]/[repo].js create mode 100644 examples/xior/pages/api/data.js create mode 100644 examples/xior/pages/index.js diff --git a/examples/xior-typescript/README.md b/examples/xior-typescript/README.md new file mode 100644 index 000000000..6de1853cb --- /dev/null +++ b/examples/xior-typescript/README.md @@ -0,0 +1,30 @@ +# Xior TypeScript + +## One-Click Deploy + +Deploy your own SWR project with Vercel. + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/xior-typescript) + +## How to Use + +Download the example: + +```bash +curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/xior-typescript +cd xior-typescript +``` + +Install it and run: + +```bash +yarn +yarn dev +# or +npm install +npm run dev +``` + +## The Idea behind the Example + +Show how to use the basic xior along with TypeScript to type both the request object and the data received from SWR. diff --git a/examples/xior-typescript/libs/useRequest.ts b/examples/xior-typescript/libs/useRequest.ts new file mode 100644 index 000000000..1e4d6c7a2 --- /dev/null +++ b/examples/xior-typescript/libs/useRequest.ts @@ -0,0 +1,66 @@ +import useSWR, { SWRConfiguration, SWRResponse } from 'swr' +import axios, { + XiorRequestConfig as AxiosRequestConfig, + XiorResponse as AxiosResponse, + XiorError as AxiosError +} from 'xior' + +export type GetRequest = AxiosRequestConfig | null + +interface Return + extends Pick< + SWRResponse, AxiosError>, + 'isValidating' | 'error' | 'mutate' + > { + data: Data | undefined + response: AxiosResponse | undefined +} + +export interface Config + extends Omit< + SWRConfiguration, AxiosError>, + 'fallbackData' + > { + fallbackData?: Data +} + +export default function useRequest( + request: GetRequest, + { fallbackData, ...config }: Config = {} +): Return { + const { + data: response, + error, + isValidating, + mutate + } = useSWR, AxiosError>( + request, + /** + * NOTE: Typescript thinks `request` can be `null` here, but the fetcher + * function is actually only called by `useSWR` when it isn't. + */ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + () => axios.request(request!), + { + ...config, + fallbackData: + fallbackData && + ({ + status: 200, + statusText: 'InitialData', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + config: request!, + headers: {}, + data: fallbackData + } as AxiosResponse) + } + ) + + return { + data: response && response.data, + response, + error, + isValidating, + mutate + } +} diff --git a/examples/xior-typescript/next-env.d.ts b/examples/xior-typescript/next-env.d.ts new file mode 100644 index 000000000..4f11a03dc --- /dev/null +++ b/examples/xior-typescript/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/xior-typescript/package.json b/examples/xior-typescript/package.json new file mode 100644 index 000000000..fbffa7f97 --- /dev/null +++ b/examples/xior-typescript/package.json @@ -0,0 +1,23 @@ +{ + "name": "xior-typescript", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "xior": "^0.2.4", + "next": "latest", + "react": "latest", + "react-dom": "latest", + "swr": "latest" + }, + "scripts": { + "dev": "next", + "start": "next start", + "build": "next build" + }, + "devDependencies": { + "@types/node": "16.7.2", + "@types/react": "17.0.19", + "typescript": "4.3.5" + } +} diff --git a/examples/xior-typescript/pages/[user]/[repo].tsx b/examples/xior-typescript/pages/[user]/[repo].tsx new file mode 100644 index 000000000..bb2b0faca --- /dev/null +++ b/examples/xior-typescript/pages/[user]/[repo].tsx @@ -0,0 +1,34 @@ +import Link from 'next/link' + +import useRequest from '../../libs/useRequest' + +export default function Repo() { + const id = + typeof window !== 'undefined' ? window.location.pathname.slice(1) : '' + const { data } = useRequest<{ + forks_count: number + stargazers_count: number + watchers: number + }>({ + url: '/api/data', + params: { id } + }) + + return ( +
+

{id}

+ {data ? ( +
+

forks: {data.forks_count}

+

stars: {data.stargazers_count}

+

watchers: {data.watchers}

+
+ ) : ( + 'loading...' + )} +
+
+ Back +
+ ) +} diff --git a/examples/xior-typescript/pages/api/data.ts b/examples/xior-typescript/pages/api/data.ts new file mode 100644 index 000000000..cc831190f --- /dev/null +++ b/examples/xior-typescript/pages/api/data.ts @@ -0,0 +1,28 @@ +import { NextApiRequest, NextApiResponse } from 'next' +import axios from 'xior' + +const projects = [ + 'facebook/flipper', + 'vuejs/vuepress', + 'rust-lang/rust', + 'vercel/next.js' +] + +export default function api(req: NextApiRequest, res: NextApiResponse) { + if (req.query.id) { + // a slow endpoint for getting repo data + axios + .request(`https://api.github.com/repos/${req.query.id}`) + .then(response => response.data) + .then(data => { + setTimeout(() => { + res.json(data) + }, 2000) + }) + + return + } + setTimeout(() => { + res.json(projects) + }, 2000) +} diff --git a/examples/xior-typescript/pages/index.tsx b/examples/xior-typescript/pages/index.tsx new file mode 100644 index 000000000..c96f3c3ae --- /dev/null +++ b/examples/xior-typescript/pages/index.tsx @@ -0,0 +1,26 @@ +import Link from 'next/link' + +import useRequest from '../libs/useRequest' + +export default function Index() { + const { data } = useRequest({ + url: '/api/data' + }) + + return ( +
+

Trending Projects

+
+ {data + ? data.map(project => ( +

+ + {project} + +

+ )) + : 'loading...'} +
+
+ ) +} diff --git a/examples/xior-typescript/tsconfig.json b/examples/xior-typescript/tsconfig.json new file mode 100644 index 000000000..7fca0e450 --- /dev/null +++ b/examples/xior-typescript/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "exclude": [ + "node_modules" + ], + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx" + ] +} diff --git a/examples/xior/README.md b/examples/xior/README.md new file mode 100644 index 000000000..27a393635 --- /dev/null +++ b/examples/xior/README.md @@ -0,0 +1,30 @@ +# Xior + +## One-Click Deploy + +Deploy your own SWR project with Vercel. + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?s=https://github.com/vercel/swr/tree/main/examples/xior) + +## How to Use + +Download the example: + +```bash +curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip=2 swr-main/examples/xior +cd xior +``` + +Install it and run: + +```bash +yarn +yarn dev +# or +npm install +npm run dev +``` + +## The Idea behind the Example + +Show a basic usage of SWR fetching using xior and a request object. diff --git a/examples/xior/libs/useRequest.js b/examples/xior/libs/useRequest.js new file mode 100644 index 000000000..fa5cb95cc --- /dev/null +++ b/examples/xior/libs/useRequest.js @@ -0,0 +1,18 @@ +import useSWR from 'swr' +import axios from 'xior' + +export default function useRequest(request, { fallbackData, ...config } = {}) { + return useSWR( + request, + () => axios.request(request || {}).then(response => response.data), + { + ...config, + fallbackData: fallbackData && { + status: 200, + statusText: 'InitialData', + headers: {}, + data: fallbackData + } + } + ) +} diff --git a/examples/xior/package.json b/examples/xior/package.json new file mode 100644 index 000000000..06791dce2 --- /dev/null +++ b/examples/xior/package.json @@ -0,0 +1,18 @@ +{ + "name": "xior-example", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "xior": "^0.2.4", + "next": "latest", + "react": "latest", + "react-dom": "latest", + "swr": "latest" + }, + "scripts": { + "dev": "next", + "start": "next start", + "build": "next build" + } +} diff --git a/examples/xior/pages/[user]/[repo].js b/examples/xior/pages/[user]/[repo].js new file mode 100644 index 000000000..e41c3346b --- /dev/null +++ b/examples/xior/pages/[user]/[repo].js @@ -0,0 +1,38 @@ +import Link from 'next/link' + +import useRequest from '../../libs/useRequest' + +export default function Repo() { + const id = + typeof window !== 'undefined' ? window.location.pathname.slice(1) : '' + const { data } = useRequest( + id + ? { + url: '/api/data', + params: { + id + } + } + : null + ) + + return ( +
+

{id}

+ {data ? ( +
+

forks: {data.forks_count}

+

stars: {data.stargazers_count}

+

watchers: {data.watchers}

+
+ ) : ( + 'loading...' + )} +
+
+ + Back + +
+ ) +} diff --git a/examples/xior/pages/api/data.js b/examples/xior/pages/api/data.js new file mode 100644 index 000000000..d98f7a297 --- /dev/null +++ b/examples/xior/pages/api/data.js @@ -0,0 +1,22 @@ +import axios from 'xior' + +const projects = [ + 'facebook/flipper', 'vuejs/vuepress', 'rust-lang/rust', 'vercel/next.js' +] + +export default function api(req, res) { + if (req.query.id) { + // a slow endpoint for getting repo data + axios.request(`https://api.github.com/repos/${req.query.id}`) + .then(resp => resp.data) + .then(data => { + setTimeout(() => { + res.json(data) + }, 2000) + }) + return + } + setTimeout(() => { + res.json(projects) + }, 2000) +} diff --git a/examples/xior/pages/index.js b/examples/xior/pages/index.js new file mode 100644 index 000000000..1f6ab8f2a --- /dev/null +++ b/examples/xior/pages/index.js @@ -0,0 +1,26 @@ +import Link from 'next/link' + +import useRequest from '../libs/useRequest' + +export default function Index() { + const { data } = useRequest({ + url: '/api/data' + }) + + return ( +
+

Trending Projects

+
+ {data + ? data.map(project => ( +

+ + {project} + +

+ )) + : 'loading...'} +
+
+ ) +}