From 4e98360c77aa0c6971988a78e37f5595a97aaf1f Mon Sep 17 00:00:00 2001 From: Bryan Thomas <49354825+bryanjtc@users.noreply.github.com> Date: Sat, 26 Oct 2024 01:28:59 -0500 Subject: [PATCH] docs: Add react router examples (#166) --- biome.json | 2 + .../content/docs/examples/react-router-6.md | 6 + .../content/docs/examples/react-router-7.md | 6 + examples/react-router-6-app/.gitignore | 24 + examples/react-router-6-app/index.html | 13 + examples/react-router-6-app/package.json | 35 + examples/react-router-6-app/public/vite.svg | 1 + examples/react-router-6-app/src/App.css | 41 + examples/react-router-6-app/src/App.tsx | 94 + .../react-router-6-app/src/assets/react.svg | 1 + examples/react-router-6-app/src/axios.ts | 6 + examples/react-router-6-app/src/index.css | 87 + examples/react-router-6-app/src/main.tsx | 26 + .../react-router-6-app/src/queryClient.tsx | 3 + examples/react-router-6-app/src/vite-env.d.ts | 1 + examples/react-router-6-app/tsconfig.json | 25 + .../react-router-6-app/tsconfig.node.json | 9 + examples/react-router-6-app/vite.config.ts | 7 + examples/react-router-7-app/.gitignore | 27 + examples/react-router-7-app/app/index.css | 87 + examples/react-router-7-app/app/root.tsx | 22 + examples/react-router-7-app/app/routes.ts | 4 + .../app/routes/_index/App.css | 41 + .../app/routes/_index/route.tsx | 109 ++ examples/react-router-7-app/assets/react.svg | 1 + examples/react-router-7-app/fetchClient.ts | 6 + examples/react-router-7-app/package.json | 41 + examples/react-router-7-app/providers.tsx | 27 + .../react-router-7-app/public/favicon.ico | Bin 0 -> 4286 bytes examples/react-router-7-app/public/vite.svg | 1 + examples/react-router-7-app/tsconfig.json | 33 + .../react-router-7-app/tsconfig.node.json | 9 + examples/react-router-7-app/vite-env.d.ts | 1 + examples/react-router-7-app/vite.config.ts | 11 + pnpm-lock.yaml | 1510 ++++++++++++++++- 35 files changed, 2268 insertions(+), 49 deletions(-) create mode 100644 docs/src/content/docs/examples/react-router-6.md create mode 100644 docs/src/content/docs/examples/react-router-7.md create mode 100644 examples/react-router-6-app/.gitignore create mode 100644 examples/react-router-6-app/index.html create mode 100644 examples/react-router-6-app/package.json create mode 100644 examples/react-router-6-app/public/vite.svg create mode 100644 examples/react-router-6-app/src/App.css create mode 100644 examples/react-router-6-app/src/App.tsx create mode 100644 examples/react-router-6-app/src/assets/react.svg create mode 100644 examples/react-router-6-app/src/axios.ts create mode 100644 examples/react-router-6-app/src/index.css create mode 100644 examples/react-router-6-app/src/main.tsx create mode 100644 examples/react-router-6-app/src/queryClient.tsx create mode 100644 examples/react-router-6-app/src/vite-env.d.ts create mode 100644 examples/react-router-6-app/tsconfig.json create mode 100644 examples/react-router-6-app/tsconfig.node.json create mode 100644 examples/react-router-6-app/vite.config.ts create mode 100644 examples/react-router-7-app/.gitignore create mode 100644 examples/react-router-7-app/app/index.css create mode 100644 examples/react-router-7-app/app/root.tsx create mode 100644 examples/react-router-7-app/app/routes.ts create mode 100644 examples/react-router-7-app/app/routes/_index/App.css create mode 100644 examples/react-router-7-app/app/routes/_index/route.tsx create mode 100644 examples/react-router-7-app/assets/react.svg create mode 100644 examples/react-router-7-app/fetchClient.ts create mode 100644 examples/react-router-7-app/package.json create mode 100644 examples/react-router-7-app/providers.tsx create mode 100644 examples/react-router-7-app/public/favicon.ico create mode 100644 examples/react-router-7-app/public/vite.svg create mode 100644 examples/react-router-7-app/tsconfig.json create mode 100644 examples/react-router-7-app/tsconfig.node.json create mode 100644 examples/react-router-7-app/vite-env.d.ts create mode 100644 examples/react-router-7-app/vite.config.ts diff --git a/biome.json b/biome.json index 271bd01..cf26d43 100644 --- a/biome.json +++ b/biome.json @@ -13,6 +13,8 @@ "examples/nextjs-app/.next", "examples/tanstack-router-app/openapi", "examples/tanstack-router-app/src/routeTree.gen.ts", + "examples/react-router-6-app/openapi", + "examples/react-router-7-app/openapi", "docs/.astro" ] }, diff --git a/docs/src/content/docs/examples/react-router-6.md b/docs/src/content/docs/examples/react-router-6.md new file mode 100644 index 0000000..b305373 --- /dev/null +++ b/docs/src/content/docs/examples/react-router-6.md @@ -0,0 +1,6 @@ +--- +title: React Router 6 Example +description: A simple example of using React Router 6 with OpenAPI React Query Codegen. +--- + +Example of using React Router 6 can be found in the [`examples/react-router-6-app`](https://github.com/7nohe/openapi-react-query-codegen/tree/main/examples/react-router-6-app) directory of the repository. diff --git a/docs/src/content/docs/examples/react-router-7.md b/docs/src/content/docs/examples/react-router-7.md new file mode 100644 index 0000000..7652648 --- /dev/null +++ b/docs/src/content/docs/examples/react-router-7.md @@ -0,0 +1,6 @@ +--- +title: React Router 7 Example +description: A simple example of using React Router 7 with OpenAPI React Query Codegen. +--- + +Example of using React Router 7 can be found in the [`examples/react-router-7-app`](https://github.com/7nohe/openapi-react-query-codegen/tree/main/examples/react-router-7-app) directory of the repository. diff --git a/examples/react-router-6-app/.gitignore b/examples/react-router-6-app/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/examples/react-router-6-app/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/react-router-6-app/index.html b/examples/react-router-6-app/index.html new file mode 100644 index 0000000..e0d1c84 --- /dev/null +++ b/examples/react-router-6-app/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + TS + + +
+ + + diff --git a/examples/react-router-6-app/package.json b/examples/react-router-6-app/package.json new file mode 100644 index 0000000..761c156 --- /dev/null +++ b/examples/react-router-6-app/package.json @@ -0,0 +1,35 @@ +{ + "name": "@7nohe/react-router-6-app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "run-p dev:mock dev:client", + "dev:client": "vite --clearScreen=false", + "dev:mock": "prism mock ../petstore.yaml --dynamic", + "build": "tsc && vite build", + "preview": "vite preview", + "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml --format=biome --lint=biome", + "test:generated": "tsc -p ./tsconfig.json --noEmit" + }, + "dependencies": { + "@hey-api/client-axios": "^0.2.7", + "@tanstack/react-query": "^5.59.13", + "@tanstack/react-query-devtools": "^5.32.1", + "axios": "^1.7.7", + "form-data": "~4.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.27.0" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.2", + "@stoplight/prism-cli": "^5.5.2", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.2.18", + "@vitejs/plugin-react": "^4.2.1", + "npm-run-all": "^4.1.5", + "typescript": "^5.4.5", + "vite": "^5.0.12" + } +} diff --git a/examples/react-router-6-app/public/vite.svg b/examples/react-router-6-app/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/examples/react-router-6-app/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/react-router-6-app/src/App.css b/examples/react-router-6-app/src/App.css new file mode 100644 index 0000000..2c5e2ef --- /dev/null +++ b/examples/react-router-6-app/src/App.css @@ -0,0 +1,41 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/examples/react-router-6-app/src/App.tsx b/examples/react-router-6-app/src/App.tsx new file mode 100644 index 0000000..b4f1376 --- /dev/null +++ b/examples/react-router-6-app/src/App.tsx @@ -0,0 +1,94 @@ +import "./App.css"; +import type { QueryClient } from "@tanstack/react-query"; +import { useState } from "react"; +import { type LoaderFunctionArgs, useLoaderData } from "react-router-dom"; +import { UseFindPetsKeyFn, useAddPet } from "../openapi/queries"; +import { ensureUseFindPetsData } from "../openapi/queries/ensureQueryData"; +import { useFindPetsSuspense } from "../openapi/queries/suspense"; +import { queryClient } from "./queryClient"; + +export const loader = + (queryClient: QueryClient) => async (_: LoaderFunctionArgs) => { + const queryParameters = { + query: { tags: [], limit: 10 }, + }; + + await ensureUseFindPetsData(queryClient, { + query: { tags: [], limit: 10 }, + }); + return queryParameters; + }; + +export function Compoment() { + const queryParameters = useLoaderData() as Awaited< + ReturnType> + >; + + const { data, error, refetch } = useFindPetsSuspense(queryParameters); + + const { mutate: addPet, isError } = useAddPet(); + + const [text, setText] = useState(""); + const [errorText, setErrorText] = useState(); + + if (error) + return ( +
+

Failed to fetch pets

+ +
+ ); + + return ( +
+

Pet List

+ setText(e.target.value)} + /> + + {isError && ( +

+ {errorText} +

+ )} +
    + {Array.isArray(data) && + data?.map((pet, index) => ( +
  • {pet.name}
  • + ))} +
+
+ ); +} diff --git a/examples/react-router-6-app/src/assets/react.svg b/examples/react-router-6-app/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/examples/react-router-6-app/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/react-router-6-app/src/axios.ts b/examples/react-router-6-app/src/axios.ts new file mode 100644 index 0000000..f1c0877 --- /dev/null +++ b/examples/react-router-6-app/src/axios.ts @@ -0,0 +1,6 @@ +import { client } from "../openapi/requests/services.gen"; + +client.setConfig({ + baseUrl: "http://localhost:4010", + throwOnError: true, +}); diff --git a/examples/react-router-6-app/src/index.css b/examples/react-router-6-app/src/index.css new file mode 100644 index 0000000..fe79a7d --- /dev/null +++ b/examples/react-router-6-app/src/index.css @@ -0,0 +1,87 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} + +input { + border-radius: 8px; + border: 1px solid #ccc; + padding: 0.5em; + font-size: 1em; + font-family: inherit; + background-color: #fff; + color: #000; + transition: border-color 0.25s; + margin: 1em; +} + +input:focus { + border-color: #646cff; + outline: none; +} diff --git a/examples/react-router-6-app/src/main.tsx b/examples/react-router-6-app/src/main.tsx new file mode 100644 index 0000000..5656b4d --- /dev/null +++ b/examples/react-router-6-app/src/main.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { Compoment, loader } from "./App"; +import "./index.css"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import { queryClient } from "./queryClient"; +import "./axios"; +import { RouterProvider, createBrowserRouter } from "react-router-dom"; + +const router = createBrowserRouter([ + { + path: "/", + element: , + loader: loader(queryClient), + }, +]); + +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + + + + + + , +); diff --git a/examples/react-router-6-app/src/queryClient.tsx b/examples/react-router-6-app/src/queryClient.tsx new file mode 100644 index 0000000..6c7b9de --- /dev/null +++ b/examples/react-router-6-app/src/queryClient.tsx @@ -0,0 +1,3 @@ +import { QueryClient } from "@tanstack/react-query"; + +export const queryClient = new QueryClient(); diff --git a/examples/react-router-6-app/src/vite-env.d.ts b/examples/react-router-6-app/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/examples/react-router-6-app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react-router-6-app/tsconfig.json b/examples/react-router-6-app/tsconfig.json new file mode 100644 index 0000000..4e730f0 --- /dev/null +++ b/examples/react-router-6-app/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/examples/react-router-6-app/tsconfig.node.json b/examples/react-router-6-app/tsconfig.node.json new file mode 100644 index 0000000..9d31e2a --- /dev/null +++ b/examples/react-router-6-app/tsconfig.node.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/examples/react-router-6-app/vite.config.ts b/examples/react-router-6-app/vite.config.ts new file mode 100644 index 0000000..1ff0da0 --- /dev/null +++ b/examples/react-router-6-app/vite.config.ts @@ -0,0 +1,7 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}); diff --git a/examples/react-router-7-app/.gitignore b/examples/react-router-7-app/.gitignore new file mode 100644 index 0000000..c2fd82b --- /dev/null +++ b/examples/react-router-7-app/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +.react-router +build \ No newline at end of file diff --git a/examples/react-router-7-app/app/index.css b/examples/react-router-7-app/app/index.css new file mode 100644 index 0000000..fe79a7d --- /dev/null +++ b/examples/react-router-7-app/app/index.css @@ -0,0 +1,87 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} + +input { + border-radius: 8px; + border: 1px solid #ccc; + padding: 0.5em; + font-size: 1em; + font-family: inherit; + background-color: #fff; + color: #000; + transition: border-color 0.25s; + margin: 1em; +} + +input:focus { + border-color: #646cff; + outline: none; +} diff --git a/examples/react-router-7-app/app/root.tsx b/examples/react-router-7-app/app/root.tsx new file mode 100644 index 0000000..314613e --- /dev/null +++ b/examples/react-router-7-app/app/root.tsx @@ -0,0 +1,22 @@ +import "./index.css"; +import { Outlet, Scripts, ScrollRestoration } from "react-router"; +import Providers from "../providers"; + +export default function Root() { + return ( + + + + + Vite + React + TS + + + + + + + + + + ); +} diff --git a/examples/react-router-7-app/app/routes.ts b/examples/react-router-7-app/app/routes.ts new file mode 100644 index 0000000..a9d70eb --- /dev/null +++ b/examples/react-router-7-app/app/routes.ts @@ -0,0 +1,4 @@ +import type { RouteConfig } from "@react-router/dev/routes"; +import { flatRoutes } from "@react-router/fs-routes"; + +export const routes: RouteConfig = flatRoutes(); diff --git a/examples/react-router-7-app/app/routes/_index/App.css b/examples/react-router-7-app/app/routes/_index/App.css new file mode 100644 index 0000000..2c5e2ef --- /dev/null +++ b/examples/react-router-7-app/app/routes/_index/App.css @@ -0,0 +1,41 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/examples/react-router-7-app/app/routes/_index/route.tsx b/examples/react-router-7-app/app/routes/_index/route.tsx new file mode 100644 index 0000000..1d9abbc --- /dev/null +++ b/examples/react-router-7-app/app/routes/_index/route.tsx @@ -0,0 +1,109 @@ +import { useState } from "react"; + +import { + HydrationBoundary, + QueryClient, + dehydrate, + useQueryClient, +} from "@tanstack/react-query"; +import { + UseFindPetsKeyFn, + useAddPet, + useFindPets, +} from "../../../openapi/queries"; +import { prefetchUseFindPets } from "../../../openapi/queries/prefetch"; +import "./App.css"; +import type * as Route from "./+types.route"; + +export async function loader({ params }: Route.LoaderArgs) { + const queryClient = new QueryClient(); + + await prefetchUseFindPets(queryClient, { + query: { tags: [], limit: 10 }, + }); + + return { dehydratedState: dehydrate(queryClient) }; +} + +function Pets() { + const queryClient = useQueryClient(); + const { data, error, refetch } = useFindPets({ + query: { tags: [], limit: 10 }, + }); + + const { mutate: addPet, isError } = useAddPet(); + + const [text, setText] = useState(""); + const [errorText, setErrorText] = useState(); + + if (error) + return ( +
+

Failed to fetch pets

+ +
+ ); + + return ( +
+

Pet List

+ setText(e.target.value)} + /> + + {isError && ( +

+ {errorText} +

+ )} +
    + {Array.isArray(data) && + data?.map((pet, index) => ( +
  • {pet.name}
  • + ))} +
+
+ ); +} + +export default function Index({ loaderData }: Route.ComponentProps) { + const { dehydratedState } = loaderData; + return ( + + + + ); +} diff --git a/examples/react-router-7-app/assets/react.svg b/examples/react-router-7-app/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/examples/react-router-7-app/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/react-router-7-app/fetchClient.ts b/examples/react-router-7-app/fetchClient.ts new file mode 100644 index 0000000..6fc2ae9 --- /dev/null +++ b/examples/react-router-7-app/fetchClient.ts @@ -0,0 +1,6 @@ +import { client } from "./openapi/requests/services.gen"; + +client.setConfig({ + baseUrl: "http://localhost:4010", + throwOnError: true, +}); diff --git a/examples/react-router-7-app/package.json b/examples/react-router-7-app/package.json new file mode 100644 index 0000000..8a28a49 --- /dev/null +++ b/examples/react-router-7-app/package.json @@ -0,0 +1,41 @@ +{ + "name": "@7nohe/react-router-7-app", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "run-p dev:mock dev:client", + "dev:client": "react-router dev", + "dev:mock": "prism mock ../petstore.yaml --dynamic", + "build": "pnpm typecheck && react-router build", + "preview": "react-router-serve ./build/server/index.js", + "typegen": "react-router typegen", + "typecheck": "pnpm typegen && tsc", + "generate:api": "rimraf ./openapi && node ../../dist/cli.mjs -i ../petstore.yaml --format=biome --lint=biome", + "test:generated": "tsc -p ./tsconfig.json --noEmit" + }, + "dependencies": { + "@react-router/fs-routes": "^7.0.0-pre.2", + "@react-router/node": "^7.0.0-pre.2", + "@react-router/serve": "^7.0.0-pre.2", + "@tanstack/react-query": "^5.59.13", + "@tanstack/react-query-devtools": "^5.32.1", + "form-data": "~4.0.0", + "isbot": "^5", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router": "^7.0.0-pre.2", + "react-router-dom": "^7.0.0-pre.2" + }, + "devDependencies": { + "@biomejs/biome": "^1.7.2", + "@react-router/dev": "^7.0.0-pre.2", + "@stoplight/prism-cli": "^5.5.2", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.2.18", + "@vitejs/plugin-react": "^4.2.1", + "npm-run-all": "^4.1.5", + "typescript": "^5.4.5", + "vite": "^5.0.12" + } +} diff --git a/examples/react-router-7-app/providers.tsx b/examples/react-router-7-app/providers.tsx new file mode 100644 index 0000000..070cf98 --- /dev/null +++ b/examples/react-router-7-app/providers.tsx @@ -0,0 +1,27 @@ +import "./fetchClient"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { QueryClient } from "@tanstack/react-query"; +import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; +import React from "react"; + +export default function Providers({ children }: { children: React.ReactNode }) { + const [queryClient] = React.useState( + () => + new QueryClient({ + defaultOptions: { + queries: { + // With SSR, we usually want to set some default staleTime + // above 0 to avoid refetching immediately on the client + staleTime: 30 * 1000, + }, + }, + }), + ); + + return ( + + {children} + + + ); +} diff --git a/examples/react-router-7-app/public/favicon.ico b/examples/react-router-7-app/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..18541a0c1bc2c3a450aad43a42900cd3ac5d1039 GIT binary patch literal 4286 zcmc(jeO%Sm9mntfY5(MFYisUhSz2jYYi#o|+uW?JoFivW$-#6rQSzAunyHl!1ZtY1 zC`kB3P#RYO69w*7NkvmJK_fL(6rE2cPr~SeaNheI;bv~HlzU&>Ysc4z-|znJ`JMAV z-}8MqSBK*}`q#0e!~S)w|GvY~*5Pn;mGsEbPqNRiH+}a|K(m@3I2`!f8Vx4)1ZLbJ zxKi)$DE_~9xC-;kZcNV|u)657T`+ zriWy&aVNp}H=IvzRn=oA?8EfV!Sr%N581%ZKOi4ItM+Lqe>$6tQ<&dvhQ3)84cf!T zki+tUmVKCY6zZG&8MbxroUg%zTEYfr=cDHStF49})f z7ns5C7hMuVEv12q!#>%VzT05Sh1-wkOOJ+YnD`x-;8mDm$(W&H7`zT-i&thI$FTwC zMQZPVvl;WmR!r!}@TJF>8E)OTP(C+qCFX^9FvC}iV=X2q1qP>*8u2lA$Q=S!UFGy( z7xep3vAGrAE4}rYt^KyPPI-2tY#)aim4JCs3?o)S@M;KJOTkOov`ee!yP5FTv`^vb z4Ef1x`#Wr zKpSb{8;2oKeyaE|LD^7T?%(V--rUM7uf2(x7K3?33=s>jGcbM$v*HeNr?$I|^t~KO zQ?=2x*ZWnR8UCRdJ`jTwGxvaUQlsw-=T*~U-@?qAiFqRmGb0)^b)Iao0KymIoS#iw zm*Iy>!9Ng#S9j&YqNqao=6lV#Vn_z;^D!Q;H7JG^U-MptnAb6LEW;d_5d~9YAaX86 zvr~9D=PT~s4nLCaR@htJrTack*&tLwq4+S*u9FQvQcm*Wj8G~+PMEHROo0W{VD1d+ zVxriPkipiaPEJLw;N$7QQE6W|>wAsm)PXfcziiJi%y+_T)H)Yg8l=9Jp+f%~NPD!pFat5W3E zl0^kDTzM;449|T|y>m6T1AAB|89D_9l)J?cqWZB$(2Y(1$xwL$T$(E*1e||` z^?y?immQMBVD(rUlO_@AF5tmK&{?i!)k!Q~S*Gg}*8{rmAl)zh)>T2-WYvn$c;)Uy z<*!sYcJb!iNbQp9VD*^PyU0U9N}39?&ELw~)1)b? zArYz};i_Y{mQIM*8s$L8w7#Mzp-}S{>i)>fdM5VM>*1n;xv~W6uBeWBNUt(<*T-Lc zenUSOk5^xFiEpL-J#y)SY5GheZ