From 0246a8e0a7e93974fb4017da9dee901f73eeff19 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Tue, 15 Jul 2025 22:22:39 +0200 Subject: [PATCH 01/11] rename query integration to react-router-ssr-query --- .../basic-react-query/package.json | 2 +- .../basic-react-query/src/router.tsx | 2 +- .../start-basic-react-query/package.json | 2 +- .../start-basic-react-query/src/router.tsx | 2 +- .../react/start-convex-trellaux/package.json | 2 +- .../start-convex-trellaux/src/router.tsx | 2 +- examples/react/start-trellaux/package.json | 2 +- examples/react/start-trellaux/src/router.tsx | 2 +- labeler-config.yml | 4 +- package.json | 2 +- .../README.md | 0 .../eslint.config.js | 0 .../package.json | 4 +- .../src/index.tsx | 0 .../tests/index.test-d.ts | 0 .../tsconfig.json | 0 .../vite.config.ts | 0 pnpm-lock.yaml | 56 +++++++++---------- scripts/publish.js | 4 +- 19 files changed, 43 insertions(+), 43 deletions(-) rename packages/{react-router-with-query => react-router-ssr-query}/README.md (100%) rename packages/{react-router-with-query => react-router-ssr-query}/eslint.config.js (100%) rename packages/{react-router-with-query => react-router-ssr-query}/package.json (95%) rename packages/{react-router-with-query => react-router-ssr-query}/src/index.tsx (100%) rename packages/{react-router-with-query => react-router-ssr-query}/tests/index.test-d.ts (100%) rename packages/{react-router-with-query => react-router-ssr-query}/tsconfig.json (100%) rename packages/{react-router-with-query => react-router-ssr-query}/vite.config.ts (100%) diff --git a/e2e/react-start/basic-react-query/package.json b/e2e/react-start/basic-react-query/package.json index e8e60685eb..84dc5c3c59 100644 --- a/e2e/react-start/basic-react-query/package.json +++ b/e2e/react-start/basic-react-query/package.json @@ -15,7 +15,7 @@ "@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-router": "workspace:^", "@tanstack/react-router-devtools": "workspace:^", - "@tanstack/react-router-with-query": "workspace:^", + "@tanstack/react-router-ssr-query": "workspace:^", "@tanstack/react-start": "workspace:^", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/e2e/react-start/basic-react-query/src/router.tsx b/e2e/react-start/basic-react-query/src/router.tsx index 7e155cd75e..9a2fc110d0 100644 --- a/e2e/react-start/basic-react-query/src/router.tsx +++ b/e2e/react-start/basic-react-query/src/router.tsx @@ -1,6 +1,6 @@ import { QueryClient } from '@tanstack/react-query' import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routerWithQueryClient } from '@tanstack/react-router-with-query' +import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' import { NotFound } from './components/NotFound' diff --git a/examples/react/start-basic-react-query/package.json b/examples/react/start-basic-react-query/package.json index 821c314832..fc4165073a 100644 --- a/examples/react/start-basic-react-query/package.json +++ b/examples/react/start-basic-react-query/package.json @@ -12,7 +12,7 @@ "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-router": "^1.127.8", - "@tanstack/react-router-with-query": "^1.127.8", + "@tanstack/react-router-ssr-query": "^1.127.8", "@tanstack/react-router-devtools": "^1.127.8", "@tanstack/react-start": "^1.127.8", "react": "^19.0.0", diff --git a/examples/react/start-basic-react-query/src/router.tsx b/examples/react/start-basic-react-query/src/router.tsx index ee35b01cbf..1713444ae9 100644 --- a/examples/react/start-basic-react-query/src/router.tsx +++ b/examples/react/start-basic-react-query/src/router.tsx @@ -1,6 +1,6 @@ import { QueryClient } from '@tanstack/react-query' import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routerWithQueryClient } from '@tanstack/react-router-with-query' +import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' import { NotFound } from './components/NotFound' diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json index a5ddab4f83..0f96d0caa2 100644 --- a/examples/react/start-convex-trellaux/package.json +++ b/examples/react/start-convex-trellaux/package.json @@ -15,7 +15,7 @@ "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-router": "^1.127.8", - "@tanstack/react-router-with-query": "^1.127.8", + "@tanstack/react-router-ssr-query": "^1.127.8", "@tanstack/react-router-devtools": "^1.127.8", "@tanstack/react-start": "^1.127.8", "concurrently": "^8.2.2", diff --git a/examples/react/start-convex-trellaux/src/router.tsx b/examples/react/start-convex-trellaux/src/router.tsx index 21444891bf..488c1def5e 100644 --- a/examples/react/start-convex-trellaux/src/router.tsx +++ b/examples/react/start-convex-trellaux/src/router.tsx @@ -4,7 +4,7 @@ import { QueryClient, notifyManager, } from '@tanstack/react-query' -import { routerWithQueryClient } from '@tanstack/react-router-with-query' +import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' import toast from 'react-hot-toast' import { ConvexQueryClient } from '@convex-dev/react-query' import { ConvexProvider } from 'convex/react' diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json index cba20fe6b5..4ca2ee3545 100644 --- a/examples/react/start-trellaux/package.json +++ b/examples/react/start-trellaux/package.json @@ -12,7 +12,7 @@ "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", "@tanstack/react-router": "^1.127.8", - "@tanstack/react-router-with-query": "^1.127.8", + "@tanstack/react-router-ssr-query": "^1.127.8", "@tanstack/react-router-devtools": "^1.127.8", "@tanstack/react-start": "^1.127.8", "ky": "^1.7.4", diff --git a/examples/react/start-trellaux/src/router.tsx b/examples/react/start-trellaux/src/router.tsx index e31d571dc6..52b663718b 100644 --- a/examples/react/start-trellaux/src/router.tsx +++ b/examples/react/start-trellaux/src/router.tsx @@ -4,7 +4,7 @@ import { QueryClient, notifyManager, } from '@tanstack/react-query' -import { routerWithQueryClient } from '@tanstack/react-router-with-query' +import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' import toast from 'react-hot-toast' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' diff --git a/labeler-config.yml b/labeler-config.yml index 40fd47941c..6c6ababe01 100644 --- a/labeler-config.yml +++ b/labeler-config.yml @@ -16,9 +16,9 @@ 'package: react-router-devtools': - changed-files: - any-glob-to-any-file: 'packages/react-router-devtools/**/*' -'package: react-router-with-query': +'package: react-router-ssr-query': - changed-files: - - any-glob-to-any-file: 'packages/react-router-with-query/**/*' + - any-glob-to-any-file: 'packages/react-router-ssr-query/**/*' 'package: react-start': - changed-files: - any-glob-to-any-file: 'packages/react-start/**/*' diff --git a/package.json b/package.json index f95ea9c054..d9204ab9e8 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "@tanstack/virtual-file-routes": "workspace:*", "@tanstack/router-plugin": "workspace:*", "@tanstack/router-vite-plugin": "workspace:*", - "@tanstack/react-router-with-query": "workspace:*", + "@tanstack/react-router-ssr-query": "workspace:*", "@tanstack/zod-adapter": "workspace:*", "@tanstack/valibot-adapter": "workspace:*", "@tanstack/arktype-adapter": "workspace:*", diff --git a/packages/react-router-with-query/README.md b/packages/react-router-ssr-query/README.md similarity index 100% rename from packages/react-router-with-query/README.md rename to packages/react-router-ssr-query/README.md diff --git a/packages/react-router-with-query/eslint.config.js b/packages/react-router-ssr-query/eslint.config.js similarity index 100% rename from packages/react-router-with-query/eslint.config.js rename to packages/react-router-ssr-query/eslint.config.js diff --git a/packages/react-router-with-query/package.json b/packages/react-router-ssr-query/package.json similarity index 95% rename from packages/react-router-with-query/package.json rename to packages/react-router-ssr-query/package.json index 3878074bff..04a067ee9d 100644 --- a/packages/react-router-with-query/package.json +++ b/packages/react-router-ssr-query/package.json @@ -1,5 +1,5 @@ { - "name": "@tanstack/react-router-with-query", + "name": "@tanstack/react-router-ssr-query", "version": "1.127.8", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", @@ -7,7 +7,7 @@ "repository": { "type": "git", "url": "https://github.com/TanStack/router.git", - "directory": "packages/react-router-with-query" + "directory": "packages/react-router-ssr-query" }, "homepage": "https://tanstack.com/router", "funding": { diff --git a/packages/react-router-with-query/src/index.tsx b/packages/react-router-ssr-query/src/index.tsx similarity index 100% rename from packages/react-router-with-query/src/index.tsx rename to packages/react-router-ssr-query/src/index.tsx diff --git a/packages/react-router-with-query/tests/index.test-d.ts b/packages/react-router-ssr-query/tests/index.test-d.ts similarity index 100% rename from packages/react-router-with-query/tests/index.test-d.ts rename to packages/react-router-ssr-query/tests/index.test-d.ts diff --git a/packages/react-router-with-query/tsconfig.json b/packages/react-router-ssr-query/tsconfig.json similarity index 100% rename from packages/react-router-with-query/tsconfig.json rename to packages/react-router-ssr-query/tsconfig.json diff --git a/packages/react-router-with-query/vite.config.ts b/packages/react-router-ssr-query/vite.config.ts similarity index 100% rename from packages/react-router-with-query/vite.config.ts rename to packages/react-router-ssr-query/vite.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b332ea2fd4..9191ee05bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,7 +26,7 @@ overrides: '@tanstack/virtual-file-routes': workspace:* '@tanstack/router-plugin': workspace:* '@tanstack/router-vite-plugin': workspace:* - '@tanstack/react-router-with-query': workspace:* + '@tanstack/react-router-ssr-query': workspace:* '@tanstack/zod-adapter': workspace:* '@tanstack/valibot-adapter': workspace:* '@tanstack/arktype-adapter': workspace:* @@ -1080,9 +1080,9 @@ importers: '@tanstack/react-router-devtools': specifier: workspace:^ version: link:../../../packages/react-router-devtools - '@tanstack/react-router-with-query': + '@tanstack/react-router-ssr-query': specifier: workspace:* - version: link:../../../packages/react-router-with-query + version: link:../../../packages/react-router-ssr-query '@tanstack/react-start': specifier: workspace:* version: link:../../../packages/react-start @@ -3838,10 +3838,10 @@ importers: version: 19.0.3(@types/react@19.0.8) html-webpack-plugin: specifier: ^5.6.3 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) typescript: specifier: ^5.7.2 version: 5.8.2 @@ -4676,9 +4676,9 @@ importers: '@tanstack/react-router-devtools': specifier: workspace:^ version: link:../../../packages/react-router-devtools - '@tanstack/react-router-with-query': + '@tanstack/react-router-ssr-query': specifier: workspace:* - version: link:../../../packages/react-router-with-query + version: link:../../../packages/react-router-ssr-query '@tanstack/react-start': specifier: workspace:* version: link:../../../packages/react-start @@ -4899,9 +4899,9 @@ importers: '@tanstack/react-router-devtools': specifier: workspace:^ version: link:../../../packages/react-router-devtools - '@tanstack/react-router-with-query': + '@tanstack/react-router-ssr-query': specifier: workspace:* - version: link:../../../packages/react-router-with-query + version: link:../../../packages/react-router-ssr-query '@tanstack/react-start': specifier: workspace:* version: link:../../../packages/react-start @@ -5226,9 +5226,9 @@ importers: '@tanstack/react-router-devtools': specifier: workspace:^ version: link:../../../packages/react-router-devtools - '@tanstack/react-router-with-query': + '@tanstack/react-router-ssr-query': specifier: workspace:* - version: link:../../../packages/react-router-with-query + version: link:../../../packages/react-router-ssr-query '@tanstack/react-start': specifier: workspace:* version: link:../../../packages/react-start @@ -6232,7 +6232,7 @@ importers: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - packages/react-router-with-query: + packages/react-router-ssr-query: devDependencies: '@tanstack/react-query': specifier: 5.66.0 @@ -6245,7 +6245,7 @@ importers: version: link:../router-core '@vitejs/plugin-react': specifier: ^4.3.4 - version: 4.3.4(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) + version: 4.6.0(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) react: specifier: ^19.0.0 version: 19.0.0 @@ -19788,17 +19788,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) @@ -21839,7 +21839,7 @@ snapshots: html-tags@3.3.1: {} - html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1): + html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -24148,7 +24148,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1): + swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)): dependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) '@swc/counter': 0.1.3 @@ -24220,26 +24220,26 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.4 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.4 @@ -24898,9 +24898,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -24914,7 +24914,7 @@ snapshots: optionalDependencies: webpack-dev-server: 5.2.0(webpack-cli@5.1.4)(webpack@5.97.1) - webpack-dev-middleware@7.4.2(webpack@5.97.1): + webpack-dev-middleware@7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)): dependencies: colorette: 2.0.20 memfs: 4.17.0 @@ -24952,7 +24952,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.97.1) + webpack-dev-middleware: 7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) ws: 8.18.0 optionalDependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4) @@ -25027,7 +25027,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.4)(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: diff --git a/scripts/publish.js b/scripts/publish.js index 0f8c7d0e98..c5e0ea1de8 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -25,8 +25,8 @@ await publish({ packageDir: 'packages/react-router', }, { - name: '@tanstack/react-router-with-query', - packageDir: 'packages/react-router-with-query', + name: '@tanstack/react-router-ssr-query', + packageDir: 'packages/react-router-ssr-query', }, { name: '@tanstack/zod-adapter', From 2d9ef91028a537599bd0753d0bc63eafdf6507d5 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 01:34:24 +0200 Subject: [PATCH 02/11] move query integration into a separate package also renamed init function --- .../start-basic-react-query/src/router.tsx | 27 ++- package.json | 5 +- packages/react-router-ssr-query/package.json | 10 +- packages/react-router-ssr-query/src/index.tsx | 210 ++---------------- packages/router-ssr-query-core/README.md | 5 + .../router-ssr-query-core/eslint.config.js | 14 ++ packages/router-ssr-query-core/package.json | 74 ++++++ packages/router-ssr-query-core/src/index.ts | 196 ++++++++++++++++ packages/router-ssr-query-core/tsconfig.json | 4 + packages/router-ssr-query-core/vite.config.ts | 22 ++ pnpm-lock.yaml | 31 ++- 11 files changed, 378 insertions(+), 220 deletions(-) create mode 100644 packages/router-ssr-query-core/README.md create mode 100644 packages/router-ssr-query-core/eslint.config.js create mode 100644 packages/router-ssr-query-core/package.json create mode 100644 packages/router-ssr-query-core/src/index.ts create mode 100644 packages/router-ssr-query-core/tsconfig.json create mode 100644 packages/router-ssr-query-core/vite.config.ts diff --git a/examples/react/start-basic-react-query/src/router.tsx b/examples/react/start-basic-react-query/src/router.tsx index 1713444ae9..fe06f5cd68 100644 --- a/examples/react/start-basic-react-query/src/router.tsx +++ b/examples/react/start-basic-react-query/src/router.tsx @@ -1,27 +1,26 @@ import { QueryClient } from '@tanstack/react-query' import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' +import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' import { NotFound } from './components/NotFound' -// NOTE: Most of the integration code found here is experimental and will -// definitely end up in a more streamlined API in the future. This is just -// to show what's possible with the current APIs. - export function createRouter() { const queryClient = new QueryClient() - return routerWithQueryClient( - createTanStackRouter({ - routeTree, - context: { queryClient }, - defaultPreload: 'intent', - defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => , - }), + const router = createTanStackRouter({ + routeTree, + context: { queryClient }, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + }) + setupRouterSsrQueryIntegration({ + router, queryClient, - ) + }) + + return router } declare module '@tanstack/react-router' { diff --git a/package.json b/package.json index d9204ab9e8..1a2e7f2ae9 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@playwright/test": "^1.52.0", "@tanstack/config": "^0.16.1", "@tanstack/react-query": "5.66.0", + "@tanstack/query-core": "5.66.0", "@types/node": "^22.10.2", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", @@ -80,7 +81,8 @@ "eslint": "$eslint", "vite": "$vite", "@playwright/test": "$@playwright/test", - "@tanstack/react-query": "5.66.0", + "@tanstack/react-query": "$@tanstack/react-query", + "@tanstack/query-core": "$@tanstack/query-core", "use-sync-external-store": "1.2.2", "@tanstack/history": "workspace:*", "@tanstack/router-core": "workspace:*", @@ -94,6 +96,7 @@ "@tanstack/virtual-file-routes": "workspace:*", "@tanstack/router-plugin": "workspace:*", "@tanstack/router-vite-plugin": "workspace:*", + "@tanstack/router-ssr-query-core": "workspace:*", "@tanstack/react-router-ssr-query": "workspace:*", "@tanstack/zod-adapter": "workspace:*", "@tanstack/valibot-adapter": "workspace:*", diff --git a/packages/react-router-ssr-query/package.json b/packages/react-router-ssr-query/package.json index 04a067ee9d..7d401f99ea 100644 --- a/packages/react-router-ssr-query/package.json +++ b/packages/react-router-ssr-query/package.json @@ -63,19 +63,21 @@ "engines": { "node": ">=12" }, + "dependencies": { + "@tanstack/router-ssr-query-core": "workspace:^" + }, "devDependencies": { "@vitejs/plugin-react": "^4.3.4", "react": ">=19", "react-dom": ">=19", - "@tanstack/router-core": "workspace:^", "@tanstack/react-router": "workspace:^", - "@tanstack/react-query": ">=5.66.0" + "@tanstack/react-query": ">=5.49.0" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", - "@tanstack/router-core": ">=1.114.7", - "@tanstack/react-router": ">=1.43.2", + "@tanstack/query-core": ">=5.49.0", + "@tanstack/react-router": ">=1.127.0", "@tanstack/react-query": ">=5.49.2" } } diff --git a/packages/react-router-ssr-query/src/index.tsx b/packages/react-router-ssr-query/src/index.tsx index af0d3eb951..80496c0c90 100644 --- a/packages/react-router-ssr-query/src/index.tsx +++ b/packages/react-router-ssr-query/src/index.tsx @@ -1,209 +1,35 @@ import { Fragment } from 'react' -import { - QueryClientProvider, - dehydrate as queryDehydrate, - hydrate as queryHydrate, -} from '@tanstack/react-query' -import { isRedirect } from '@tanstack/router-core' -import '@tanstack/router-core/ssr/client' +import { QueryClientProvider } from '@tanstack/react-query' import type { AnyRouter } from '@tanstack/react-router' -import type { - QueryClient, - DehydratedState as QueryDehydratedState, -} from '@tanstack/react-query' - -type AdditionalOptions = { - WrapProvider?: (props: { children: any }) => React.JSX.Element - /** - * If `true`, the QueryClient will handle errors thrown by `redirect()` inside of mutations and queries. - * - * @default true - * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction) - */ - handleRedirects?: boolean -} +import { + RouterSsrQueryOptions, + setupCoreRouterSsrQueryIntegration, +} from '@tanstack/router-ssr-query-core' -type DehydratedRouterQueryState = { - dehydratedQueryClient: QueryDehydratedState - queryStream: ReadableStream -} -export type ValidateRouter = - NonNullable extends { - queryClient: QueryClient +export type Options = + RouterSsrQueryOptions & { + WrapProvider?: (props: { children: any }) => React.JSX.Element } - ? TRouter - : never -export function routerWithQueryClient( - router: ValidateRouter, - queryClient: QueryClient, - additionalOpts?: AdditionalOptions, -): TRouter { - const ogOptions = router.options +export function setupRouterSsrQueryIntegration( + opts: Options, +) { + setupCoreRouterSsrQueryIntegration(opts) - router.options = { - ...router.options, - context: { - ...ogOptions.context, - // Pass the query client to the context, so we can access it in loaders - queryClient, - }, - // Wrap the app in a QueryClientProvider + const ogOptions = opts.router.options + + opts.router.options = { + ...ogOptions, Wrap: ({ children }) => { - const OuterWrapper = additionalOpts?.WrapProvider || Fragment + const OuterWrapper = opts?.WrapProvider || Fragment const OGWrap = ogOptions.Wrap || Fragment return ( - + {children} ) }, } - - if (router.isServer) { - const queryStream = createPushableStream() - - router.options.dehydrate = - async (): Promise => { - const ogDehydrated = await ogOptions.dehydrate?.() - const dehydratedQueryClient = queryDehydrate(queryClient) - - router.serverSsr!.onRenderFinished(() => queryStream.close()) - - const dehydratedRouter = { - ...ogDehydrated, - // When critical data is dehydrated, we also dehydrate the query client - dehydratedQueryClient, - // prepare the stream for queries coming up during rendering - queryStream: queryStream.stream, - } - - return dehydratedRouter - } - - const ogClientOptions = queryClient.getDefaultOptions() - queryClient.setDefaultOptions({ - ...ogClientOptions, - dehydrate: { - shouldDehydrateQuery: () => true, - ...ogClientOptions.dehydrate, - }, - }) - - queryClient.getQueryCache().subscribe((event) => { - if (event.type === 'added') { - // before rendering starts, we do not stream individual queries - // instead we dehydrate the entire query client in router's dehydrate() - if (!router.serverSsr!.isDehydrated()) { - return - } - if (queryStream.isClosed()) { - console.warn( - `tried to stream query ${event.query.queryHash} after stream was already closed`, - ) - return - } - queryStream.enqueue( - queryDehydrate(queryClient, { - shouldDehydrateQuery: (query) => { - if (query.queryHash === event.query.queryHash) { - return ( - ogClientOptions.dehydrate?.shouldDehydrateQuery?.(query) ?? - true - ) - } - return false - }, - }), - ) - } - }) - // on the client - } else { - router.options.hydrate = async (dehydrated: DehydratedRouterQueryState) => { - await ogOptions.hydrate?.(dehydrated) - // On the client, hydrate the query client with the dehydrated data - queryHydrate(queryClient, dehydrated.dehydratedQueryClient) - - const reader = dehydrated.queryStream.getReader() - reader - .read() - .then(async function handle({ done, value }) { - queryHydrate(queryClient, value) - if (done) { - return - } - const result = await reader.read() - return handle(result) - }) - .catch((err) => { - console.error('Error reading query stream:', err) - }) - } - if (additionalOpts?.handleRedirects ?? true) { - const ogMutationCacheConfig = queryClient.getMutationCache().config - queryClient.getMutationCache().config = { - ...ogMutationCacheConfig, - onError: (error, _variables, _context, _mutation) => { - if (isRedirect(error)) { - error.options._fromLocation = router.state.location - return router.navigate(router.resolveRedirect(error).options) - } - - return ogMutationCacheConfig.onError?.( - error, - _variables, - _context, - _mutation, - ) - }, - } - - const ogQueryCacheConfig = queryClient.getQueryCache().config - queryClient.getQueryCache().config = { - ...ogQueryCacheConfig, - onError: (error, _query) => { - if (isRedirect(error)) { - error.options._fromLocation = router.state.location - return router.navigate(router.resolveRedirect(error).options) - } - - return ogQueryCacheConfig.onError?.(error, _query) - }, - } - } - } - - return router -} - -type PushableStream = { - stream: ReadableStream - enqueue: (chunk: unknown) => void - close: () => void - isClosed: () => boolean - error: (err: unknown) => void -} - -function createPushableStream(): PushableStream { - let controllerRef: ReadableStreamDefaultController - const stream = new ReadableStream({ - start(controller) { - controllerRef = controller - }, - }) - let _isClosed = false - - return { - stream, - enqueue: (chunk) => controllerRef.enqueue(chunk), - close: () => { - controllerRef.close() - _isClosed = true - }, - isClosed: () => _isClosed, - error: (err: unknown) => controllerRef.error(err), - } } diff --git a/packages/router-ssr-query-core/README.md b/packages/router-ssr-query-core/README.md new file mode 100644 index 0000000000..b3a422c890 --- /dev/null +++ b/packages/router-ssr-query-core/README.md @@ -0,0 +1,5 @@ + + +# TanStack Router Core + +See [https://tanstack.com/router](https://tanstack.com/router) for documentation. diff --git a/packages/router-ssr-query-core/eslint.config.js b/packages/router-ssr-query-core/eslint.config.js new file mode 100644 index 0000000000..657b7e420b --- /dev/null +++ b/packages/router-ssr-query-core/eslint.config.js @@ -0,0 +1,14 @@ +// @ts-check + +import rootConfig from '../../eslint.config.js' + +export default [ + ...rootConfig, + { + files: ['src/**/*.{ts,tsx}', 'tests/**/*.{ts,tsx}'], + rules: { + 'unused-imports/no-unused-vars': 'off', + '@typescript-eslint/no-unnecessary-condition': 'off', + }, + }, +] diff --git a/packages/router-ssr-query-core/package.json b/packages/router-ssr-query-core/package.json new file mode 100644 index 0000000000..48473bf29a --- /dev/null +++ b/packages/router-ssr-query-core/package.json @@ -0,0 +1,74 @@ +{ + "name": "@tanstack/router-ssr-query-core", + "version": "1.127.3", + "description": "Modern and scalable routing for React applications", + "author": "Tanner Linsley", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/TanStack/router.git", + "directory": "packages/router-ssr-query-core" + }, + "homepage": "https://tanstack.com/router", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "react", + "location", + "router", + "routing", + "async", + "async router", + "typescript" + ], + "scripts": { + "clean": "rimraf ./dist && rimraf ./coverage", + "test:eslint": "eslint ./src", + "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", + "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", + "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", + "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", + "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", + "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", + "test:types:ts58": "tsc", + "test:unit": "vitest", + "test:unit:dev": "pnpm run test:unit --watch", + "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", + "build": "vite build" + }, + "type": "module", + "types": "dist/esm/index.d.ts", + "main": "dist/cjs/index.cjs", + "module": "dist/esm/index.js", + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.cts", + "default": "./dist/cjs/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "files": [ + "dist", + "src" + ], + "engines": { + "node": ">=12" + }, + "devDependencies": { + "@tanstack/router-core": ">=1.127.0", + "@tanstack/query-core": ">=5.49.0" + }, + "peerDependencies": { + "@tanstack/router-core": ">=1.127.0", + "@tanstack/query-core": ">=5.49.0" + } +} diff --git a/packages/router-ssr-query-core/src/index.ts b/packages/router-ssr-query-core/src/index.ts new file mode 100644 index 0000000000..18d88e4689 --- /dev/null +++ b/packages/router-ssr-query-core/src/index.ts @@ -0,0 +1,196 @@ +import { + dehydrate as queryDehydrate, + hydrate as queryHydrate, +} from '@tanstack/query-core' +import { isRedirect } from '@tanstack/router-core' +import type { AnyRouter } from '@tanstack/router-core' +import type { + QueryClient, + DehydratedState as QueryDehydratedState, +} from '@tanstack/query-core' + +export type ValidateRouter = + NonNullable extends { + queryClient: QueryClient + } + ? TRouter + : never + +export type RouterSsrQueryOptions = { + router: ValidateRouter + queryClient: QueryClient + + /** + * If `true`, the QueryClient will handle errors thrown by `redirect()` inside of mutations and queries. + * + * @default true + * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/api/router/redirectFunction) + */ + handleRedirects?: boolean +} + +type DehydratedRouterQueryState = { + dehydratedQueryClient: QueryDehydratedState + queryStream: ReadableStream +} + +export function setupCoreRouterSsrQueryIntegration({ + router, + queryClient, + handleRedirects = true, +}: RouterSsrQueryOptions) { + const ogOptions = router.options + + router.options = { + ...router.options, + context: { + ...ogOptions.context, + // TODO remove this + // Pass the query client to the context, so we can access it in loaders + queryClient, + }, + } + + if (router.isServer) { + const queryStream = createPushableStream() + + router.options.dehydrate = + async (): Promise => { + const ogDehydrated = await ogOptions.dehydrate?.() + const dehydratedQueryClient = queryDehydrate(queryClient) + + router.serverSsr!.onRenderFinished(() => queryStream.close()) + + const dehydratedRouter = { + ...ogDehydrated, + // When critical data is dehydrated, we also dehydrate the query client + dehydratedQueryClient, + // prepare the stream for queries coming up during rendering + queryStream: queryStream.stream, + } + + return dehydratedRouter + } + + const ogClientOptions = queryClient.getDefaultOptions() + queryClient.setDefaultOptions({ + ...ogClientOptions, + dehydrate: { + shouldDehydrateQuery: () => true, + ...ogClientOptions.dehydrate, + }, + }) + + queryClient.getQueryCache().subscribe((event) => { + if (event.type === 'added') { + // before rendering starts, we do not stream individual queries + // instead we dehydrate the entire query client in router's dehydrate() + if (!router.serverSsr!.isDehydrated()) { + return + } + if (queryStream.isClosed()) { + console.warn( + `tried to stream query ${event.query.queryHash} after stream was already closed`, + ) + return + } + queryStream.enqueue( + queryDehydrate(queryClient, { + shouldDehydrateQuery: (query) => { + if (query.queryHash === event.query.queryHash) { + return ( + ogClientOptions.dehydrate?.shouldDehydrateQuery?.(query) ?? + true + ) + } + return false + }, + }), + ) + } + }) + // on the client + } else { + router.options.hydrate = async (dehydrated: DehydratedRouterQueryState) => { + await ogOptions.hydrate?.(dehydrated) + // On the client, hydrate the query client with the dehydrated data + queryHydrate(queryClient, dehydrated.dehydratedQueryClient) + + const reader = dehydrated.queryStream.getReader() + reader + .read() + .then(async function handle({ done, value }) { + queryHydrate(queryClient, value) + if (done) { + return + } + const result = await reader.read() + return handle(result) + }) + .catch((err) => { + console.error('Error reading query stream:', err) + }) + } + if (handleRedirects) { + const ogMutationCacheConfig = queryClient.getMutationCache().config + queryClient.getMutationCache().config = { + ...ogMutationCacheConfig, + onError: (error, _variables, _context, _mutation) => { + if (isRedirect(error)) { + error.options._fromLocation = router.state.location + return router.navigate(router.resolveRedirect(error).options) + } + + return ogMutationCacheConfig.onError?.( + error, + _variables, + _context, + _mutation, + ) + }, + } + + const ogQueryCacheConfig = queryClient.getQueryCache().config + queryClient.getQueryCache().config = { + ...ogQueryCacheConfig, + onError: (error, _query) => { + if (isRedirect(error)) { + error.options._fromLocation = router.state.location + return router.navigate(router.resolveRedirect(error).options) + } + + return ogQueryCacheConfig.onError?.(error, _query) + }, + } + } + } +} + +type PushableStream = { + stream: ReadableStream + enqueue: (chunk: unknown) => void + close: () => void + isClosed: () => boolean + error: (err: unknown) => void +} + +function createPushableStream(): PushableStream { + let controllerRef: ReadableStreamDefaultController + const stream = new ReadableStream({ + start(controller) { + controllerRef = controller + }, + }) + let _isClosed = false + + return { + stream, + enqueue: (chunk) => controllerRef.enqueue(chunk), + close: () => { + controllerRef.close() + _isClosed = true + }, + isClosed: () => _isClosed, + error: (err: unknown) => controllerRef.error(err), + } +} diff --git a/packages/router-ssr-query-core/tsconfig.json b/packages/router-ssr-query-core/tsconfig.json new file mode 100644 index 0000000000..e99dc8130a --- /dev/null +++ b/packages/router-ssr-query-core/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "vite.config.ts", "tests", "vite-minify-plugin.ts"] +} diff --git a/packages/router-ssr-query-core/vite.config.ts b/packages/router-ssr-query-core/vite.config.ts new file mode 100644 index 0000000000..f5bd8a0b05 --- /dev/null +++ b/packages/router-ssr-query-core/vite.config.ts @@ -0,0 +1,22 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/config/vite' +import packageJson from './package.json' +import type { ViteUserConfig } from 'vitest/config' + +const config = defineConfig({ + test: { + name: packageJson.name, + dir: './tests', + watch: false, + environment: 'jsdom', + typecheck: { enabled: true }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: ['./src/index.ts'], + srcDir: './src', + }), +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9191ee05bc..cdaef034f3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,7 @@ overrides: vite: 6.3.5 '@playwright/test': ^1.52.0 '@tanstack/react-query': 5.66.0 + '@tanstack/query-core': 5.66.0 '@tanstack/history': workspace:* '@tanstack/router-core': workspace:* '@tanstack/react-router': workspace:* @@ -26,6 +27,7 @@ overrides: '@tanstack/virtual-file-routes': workspace:* '@tanstack/router-plugin': workspace:* '@tanstack/router-vite-plugin': workspace:* + '@tanstack/router-ssr-query-core': workspace:* '@tanstack/react-router-ssr-query': workspace:* '@tanstack/zod-adapter': workspace:* '@tanstack/valibot-adapter': workspace:* @@ -65,6 +67,9 @@ importers: '@tanstack/config': specifier: ^0.16.1 version: 0.16.1(@types/node@22.13.4)(esbuild@0.25.4)(eslint@9.22.0(jiti@2.4.2))(rollup@4.41.1)(typescript@5.8.2)(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) + '@tanstack/query-core': + specifier: 5.66.0 + version: 5.66.0 '@tanstack/react-query': specifier: 5.66.0 version: 5.66.0(react@19.0.0) @@ -6233,6 +6238,13 @@ importers: version: 19.0.0(react@19.0.0) packages/react-router-ssr-query: + dependencies: + '@tanstack/query-core': + specifier: 5.66.0 + version: 5.66.0 + '@tanstack/router-ssr-query-core': + specifier: workspace:* + version: link:../router-ssr-query-core devDependencies: '@tanstack/react-query': specifier: 5.66.0 @@ -6240,9 +6252,6 @@ importers: '@tanstack/react-router': specifier: workspace:* version: link:../react-router - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core '@vitejs/plugin-react': specifier: ^4.3.4 version: 4.6.0(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) @@ -6575,6 +6584,15 @@ importers: specifier: ^7.20.7 version: 7.20.7 + packages/router-ssr-query-core: + devDependencies: + '@tanstack/query-core': + specifier: 5.66.0 + version: 5.66.0 + '@tanstack/router-core': + specifier: workspace:* + version: link:../router-core + packages/router-utils: dependencies: '@babel/core': @@ -10170,9 +10188,6 @@ packages: '@tanstack/query-core@5.66.0': resolution: {integrity: sha512-J+JeBtthiKxrpzUu7rfIPDzhscXF2p5zE/hVdrqkACBP8Yu0M96mwJ5m/8cPPYQE9aRNvXztXHlNwIh4FEeMZw==} - '@tanstack/query-core@5.72.2': - resolution: {integrity: sha512-fxl9/0yk3mD/FwTmVEf1/H6N5B975H0luT+icKyX566w6uJG0x6o+Yl+I38wJRCaogiMkstByt+seXfDbWDAcA==} - '@tanstack/query-devtools@5.67.2': resolution: {integrity: sha512-O4QXFFd7xqp6EX7sdvc9tsVO8nm4lpWBqwpgjpVLW5g7IeOY6VnS/xvs/YzbRhBVkKTMaJMOUGU7NhSX+YGoNg==} @@ -19027,8 +19042,6 @@ snapshots: '@tanstack/query-core@5.66.0': {} - '@tanstack/query-core@5.72.2': {} - '@tanstack/query-devtools@5.67.2': {} '@tanstack/query-devtools@5.72.2': {} @@ -19065,7 +19078,7 @@ snapshots: '@tanstack/solid-query@5.72.2(solid-js@1.9.5)': dependencies: - '@tanstack/query-core': 5.72.2 + '@tanstack/query-core': 5.66.0 solid-js: 1.9.5 '@tanstack/solid-store@0.7.0(solid-js@1.9.5)': From 3fc364a49a11dce6d75f22c225a1ec3be4913ef5 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 13 Jul 2025 23:35:44 +0000 Subject: [PATCH 03/11] ci: apply automated fixes --- labeler-config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/labeler-config.yml b/labeler-config.yml index 6c6ababe01..0fb20f9dad 100644 --- a/labeler-config.yml +++ b/labeler-config.yml @@ -49,6 +49,9 @@ 'package: router-plugin': - changed-files: - any-glob-to-any-file: 'packages/router-plugin/**/*' +'package: router-ssr-query-core': + - changed-files: + - any-glob-to-any-file: 'packages/router-ssr-query-core/**/*' 'package: router-utils': - changed-files: - any-glob-to-any-file: 'packages/router-utils/**/*' From b2e3fcb6dc6308dda7bb6f75791acfad22414b7a Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 21:01:46 +0200 Subject: [PATCH 04/11] don't enforce queryClient on context anymore --- packages/react-router-ssr-query/package.json | 2 +- packages/react-router-ssr-query/src/index.tsx | 8 +-- .../tests/index.test-d.ts | 55 ------------------- packages/router-ssr-query-core/src/index.ts | 20 +------ 4 files changed, 5 insertions(+), 80 deletions(-) delete mode 100644 packages/react-router-ssr-query/tests/index.test-d.ts diff --git a/packages/react-router-ssr-query/package.json b/packages/react-router-ssr-query/package.json index 7d401f99ea..4ba4abb3cd 100644 --- a/packages/react-router-ssr-query/package.json +++ b/packages/react-router-ssr-query/package.json @@ -33,7 +33,7 @@ "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "tsc", - "test:unit": "vitest", + "test:unit": "exit 0; vitest", "test:unit:dev": "pnpm run test:unit --watch", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", "build": "vite build" diff --git a/packages/react-router-ssr-query/src/index.tsx b/packages/react-router-ssr-query/src/index.tsx index 80496c0c90..1de3f03a5f 100644 --- a/packages/react-router-ssr-query/src/index.tsx +++ b/packages/react-router-ssr-query/src/index.tsx @@ -1,10 +1,8 @@ import { Fragment } from 'react' import { QueryClientProvider } from '@tanstack/react-query' +import { setupCoreRouterSsrQueryIntegration } from '@tanstack/router-ssr-query-core' +import type { RouterSsrQueryOptions } from '@tanstack/router-ssr-query-core' import type { AnyRouter } from '@tanstack/react-router' -import { - RouterSsrQueryOptions, - setupCoreRouterSsrQueryIntegration, -} from '@tanstack/router-ssr-query-core' export type Options = RouterSsrQueryOptions & { @@ -21,7 +19,7 @@ export function setupRouterSsrQueryIntegration( opts.router.options = { ...ogOptions, Wrap: ({ children }) => { - const OuterWrapper = opts?.WrapProvider || Fragment + const OuterWrapper = opts.WrapProvider || Fragment const OGWrap = ogOptions.Wrap || Fragment return ( diff --git a/packages/react-router-ssr-query/tests/index.test-d.ts b/packages/react-router-ssr-query/tests/index.test-d.ts deleted file mode 100644 index 77a004ce07..0000000000 --- a/packages/react-router-ssr-query/tests/index.test-d.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { QueryClient } from '@tanstack/react-query' -import { - createRootRouteWithContext, - createRouter, -} from '@tanstack/react-router' - -import { expectTypeOf, test } from 'vitest' - -import { routerWithQueryClient } from '../src' - -test('basic { queryClient } context', () => { - const root = createRootRouteWithContext<{ - queryClient: QueryClient - }>()({}) - - const queryClient = new QueryClient() - const router = createRouter({ - context: { queryClient }, - routeTree: root, - }) - - const routerWithQuery = routerWithQueryClient(router, queryClient) - expectTypeOf(routerWithQuery).toEqualTypeOf(router) -}) - -test('no context fails', () => { - const root = createRootRouteWithContext()({}) - - const queryClient = new QueryClient() - const router = createRouter({ - routeTree: root, - }) - - routerWithQueryClient( - // @ts-expect-error - QueryClient must be in context type - router, - queryClient, - ) -}) - -test('allows additional props on context', () => { - const root = createRootRouteWithContext<{ - queryClient: QueryClient - extra: string - }>()({}) - - const queryClient = new QueryClient() - const router = createRouter({ - context: { queryClient, extra: 'extra' }, - routeTree: root, - }) - - const routerWithQuery = routerWithQueryClient(router, queryClient) - expectTypeOf(routerWithQuery).toEqualTypeOf(router) -}) diff --git a/packages/router-ssr-query-core/src/index.ts b/packages/router-ssr-query-core/src/index.ts index 18d88e4689..fde413f8f8 100644 --- a/packages/router-ssr-query-core/src/index.ts +++ b/packages/router-ssr-query-core/src/index.ts @@ -8,16 +8,8 @@ import type { QueryClient, DehydratedState as QueryDehydratedState, } from '@tanstack/query-core' - -export type ValidateRouter = - NonNullable extends { - queryClient: QueryClient - } - ? TRouter - : never - export type RouterSsrQueryOptions = { - router: ValidateRouter + router: TRouter queryClient: QueryClient /** @@ -41,16 +33,6 @@ export function setupCoreRouterSsrQueryIntegration({ }: RouterSsrQueryOptions) { const ogOptions = router.options - router.options = { - ...router.options, - context: { - ...ogOptions.context, - // TODO remove this - // Pass the query client to the context, so we can access it in loaders - queryClient, - }, - } - if (router.isServer) { const queryStream = createPushableStream() From 88eb1ceaf45f60b4acbe5113cab76711df4966c4 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 21:08:10 +0200 Subject: [PATCH 05/11] use new API --- .../basic-react-query/src/router.tsx | 25 +++++++------- .../start-convex-trellaux/src/router.tsx | 33 ++++++++++--------- examples/react/start-trellaux/src/router.tsx | 27 +++++++-------- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/e2e/react-start/basic-react-query/src/router.tsx b/e2e/react-start/basic-react-query/src/router.tsx index 9a2fc110d0..6f934c4760 100644 --- a/e2e/react-start/basic-react-query/src/router.tsx +++ b/e2e/react-start/basic-react-query/src/router.tsx @@ -1,6 +1,6 @@ import { QueryClient } from '@tanstack/react-query' import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' +import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' import { NotFound } from './components/NotFound' @@ -11,18 +11,19 @@ import { NotFound } from './components/NotFound' export function createRouter() { const queryClient = new QueryClient() - - return routerWithQueryClient( - createTanStackRouter({ - routeTree, - context: { queryClient }, - scrollRestoration: true, - defaultPreload: 'intent', - defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => , - }), + const router = createTanStackRouter({ + routeTree, + context: { queryClient }, + scrollRestoration: true, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + }) + setupRouterSsrQueryIntegration({ + router, queryClient, - ) + }) + return router } declare module '@tanstack/react-router' { diff --git a/examples/react/start-convex-trellaux/src/router.tsx b/examples/react/start-convex-trellaux/src/router.tsx index 488c1def5e..c289f8b75c 100644 --- a/examples/react/start-convex-trellaux/src/router.tsx +++ b/examples/react/start-convex-trellaux/src/router.tsx @@ -4,7 +4,7 @@ import { QueryClient, notifyManager, } from '@tanstack/react-query' -import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' +import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' import toast from 'react-hot-toast' import { ConvexQueryClient } from '@convex-dev/react-query' import { ConvexProvider } from 'convex/react' @@ -38,22 +38,23 @@ export function createRouter() { }) convexQueryClient.connect(queryClient) - const router = routerWithQueryClient( - createTanStackRouter({ - routeTree, - defaultPreload: 'intent', - defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => , - context: { queryClient }, - Wrap: ({ children }) => ( - - {children} - - ), - scrollRestoration: true, - }), + const router = createTanStackRouter({ + routeTree, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + context: { queryClient }, + Wrap: ({ children }) => ( + + {children} + + ), + scrollRestoration: true, + }) + setupRouterSsrQueryIntegration({ + router, queryClient, - ) + }) return router } diff --git a/examples/react/start-trellaux/src/router.tsx b/examples/react/start-trellaux/src/router.tsx index 52b663718b..1a6a98172d 100644 --- a/examples/react/start-trellaux/src/router.tsx +++ b/examples/react/start-trellaux/src/router.tsx @@ -4,7 +4,7 @@ import { QueryClient, notifyManager, } from '@tanstack/react-query' -import { routerWithQueryClient } from '@tanstack/react-router-ssr-query' +import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' import toast from 'react-hot-toast' import { routeTree } from './routeTree.gen' import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' @@ -33,19 +33,20 @@ export function createRouter() { }), }) - const router = routerWithQueryClient( - createTanStackRouter({ - routeTree, - defaultPreload: 'intent', - defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => , - scrollRestoration: true, - context: { - queryClient, - }, - }), + const router = createTanStackRouter({ + routeTree, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + scrollRestoration: true, + context: { + queryClient, + }, + }) + setupRouterSsrQueryIntegration({ + router, queryClient, - ) + }) return router } From ebf4675e3ec31b5de5e74aec4404e22591cd7b4b Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 21:58:18 +0200 Subject: [PATCH 06/11] fix --- packages/router-ssr-query-core/src/index.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/router-ssr-query-core/src/index.ts b/packages/router-ssr-query-core/src/index.ts index fde413f8f8..f91f8d7b88 100644 --- a/packages/router-ssr-query-core/src/index.ts +++ b/packages/router-ssr-query-core/src/index.ts @@ -8,6 +8,7 @@ import type { QueryClient, DehydratedState as QueryDehydratedState, } from '@tanstack/query-core' + export type RouterSsrQueryOptions = { router: TRouter queryClient: QueryClient @@ -31,17 +32,17 @@ export function setupCoreRouterSsrQueryIntegration({ queryClient, handleRedirects = true, }: RouterSsrQueryOptions) { - const ogOptions = router.options + const ogHydrate = router.options.hydrate + const ogDehydrate = router.options.dehydrate if (router.isServer) { const queryStream = createPushableStream() router.options.dehydrate = async (): Promise => { - const ogDehydrated = await ogOptions.dehydrate?.() - const dehydratedQueryClient = queryDehydrate(queryClient) - router.serverSsr!.onRenderFinished(() => queryStream.close()) + const ogDehydrated = await ogDehydrate?.() + const dehydratedQueryClient = queryDehydrate(queryClient) const dehydratedRouter = { ...ogDehydrated, @@ -67,7 +68,8 @@ export function setupCoreRouterSsrQueryIntegration({ if (event.type === 'added') { // before rendering starts, we do not stream individual queries // instead we dehydrate the entire query client in router's dehydrate() - if (!router.serverSsr!.isDehydrated()) { + // if attachRouterServerSsrUtils() has not been called yet, `router.serverSsr` will be undefined and we also do not stream + if (!router.serverSsr?.isDehydrated()) { return } if (queryStream.isClosed()) { @@ -94,7 +96,7 @@ export function setupCoreRouterSsrQueryIntegration({ // on the client } else { router.options.hydrate = async (dehydrated: DehydratedRouterQueryState) => { - await ogOptions.hydrate?.(dehydrated) + await ogHydrate?.(dehydrated) // On the client, hydrate the query client with the dehydrated data queryHydrate(queryClient, dehydrated.dehydratedQueryClient) From 864b2149512b413ae049729cc98d58025af8aba9 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 22:02:27 +0200 Subject: [PATCH 07/11] fix --- packages/react-router-ssr-query/src/index.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/react-router-ssr-query/src/index.tsx b/packages/react-router-ssr-query/src/index.tsx index 1de3f03a5f..ff79b40976 100644 --- a/packages/react-router-ssr-query/src/index.tsx +++ b/packages/react-router-ssr-query/src/index.tsx @@ -14,13 +14,10 @@ export function setupRouterSsrQueryIntegration( ) { setupCoreRouterSsrQueryIntegration(opts) - const ogOptions = opts.router.options + const OGWrap = opts.router.options.Wrap || Fragment + const OuterWrapper = opts.WrapProvider || Fragment - opts.router.options = { - ...ogOptions, - Wrap: ({ children }) => { - const OuterWrapper = opts.WrapProvider || Fragment - const OGWrap = ogOptions.Wrap || Fragment + opts.router.options.Wrap = ({ children }) => { return ( @@ -28,6 +25,5 @@ export function setupRouterSsrQueryIntegration( ) - }, } } From 3ce96d70a19349e539201148c7ae86aa239cd66b Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 20:03:33 +0000 Subject: [PATCH 08/11] ci: apply automated fixes --- packages/react-router-ssr-query/src/index.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/react-router-ssr-query/src/index.tsx b/packages/react-router-ssr-query/src/index.tsx index ff79b40976..99b0600e62 100644 --- a/packages/react-router-ssr-query/src/index.tsx +++ b/packages/react-router-ssr-query/src/index.tsx @@ -18,12 +18,12 @@ export function setupRouterSsrQueryIntegration( const OuterWrapper = opts.WrapProvider || Fragment opts.router.options.Wrap = ({ children }) => { - return ( - - - {children} - - - ) + return ( + + + {children} + + + ) } } From 0d4222a8cbe114f118e525f957cc60cf1739abab Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Mon, 14 Jul 2025 22:15:09 +0200 Subject: [PATCH 09/11] disable test execution since no test exist yet --- packages/router-ssr-query-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/router-ssr-query-core/package.json b/packages/router-ssr-query-core/package.json index 48473bf29a..9ecec38dea 100644 --- a/packages/router-ssr-query-core/package.json +++ b/packages/router-ssr-query-core/package.json @@ -33,7 +33,7 @@ "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "tsc", - "test:unit": "vitest", + "test:unit": "exit 0; vitest", "test:unit:dev": "pnpm run test:unit --watch", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", "build": "vite build" From c39e1ddf5bcb396e6cd2ad76e58318c2baffdc93 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Tue, 15 Jul 2025 21:59:17 +0200 Subject: [PATCH 10/11] add e2e test and fix streaming --- e2e/react-start/query-integration/.gitignore | 18 +++ .../query-integration/.prettierignore | 4 + .../query-integration/package.json | 39 ++++++ .../query-integration/playwright.config.ts | 34 +++++ .../query-integration/postcss.config.mjs | 6 + .../query-integration/src/queryOptions.ts | 15 +++ .../query-integration/src/routeTree.gen.ts | 122 ++++++++++++++++++ .../query-integration/src/router.tsx | 25 ++++ .../query-integration/src/routes/__root.tsx | 87 +++++++++++++ .../query-integration/src/routes/index.tsx | 13 ++ .../src/routes/loader-fetchQuery/$type.tsx | 43 ++++++ .../query-integration/src/routes/useQuery.tsx | 22 ++++ .../src/routes/useSuspenseQuery.tsx | 20 +++ .../query-integration/src/styles/app.css | 22 ++++ .../query-integration/tailwind.config.mjs | 4 + .../query-integration/tests/app.spec.ts | 48 +++++++ .../query-integration/tests/fixture.ts | 28 ++++ .../query-integration/tsconfig.json | 22 ++++ .../query-integration/vite.config.ts | 12 ++ packages/router-ssr-query-core/src/index.ts | 76 ++++++----- pnpm-lock.yaml | 70 ++++++++++ 21 files changed, 699 insertions(+), 31 deletions(-) create mode 100644 e2e/react-start/query-integration/.gitignore create mode 100644 e2e/react-start/query-integration/.prettierignore create mode 100644 e2e/react-start/query-integration/package.json create mode 100644 e2e/react-start/query-integration/playwright.config.ts create mode 100644 e2e/react-start/query-integration/postcss.config.mjs create mode 100644 e2e/react-start/query-integration/src/queryOptions.ts create mode 100644 e2e/react-start/query-integration/src/routeTree.gen.ts create mode 100644 e2e/react-start/query-integration/src/router.tsx create mode 100644 e2e/react-start/query-integration/src/routes/__root.tsx create mode 100644 e2e/react-start/query-integration/src/routes/index.tsx create mode 100644 e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx create mode 100644 e2e/react-start/query-integration/src/routes/useQuery.tsx create mode 100644 e2e/react-start/query-integration/src/routes/useSuspenseQuery.tsx create mode 100644 e2e/react-start/query-integration/src/styles/app.css create mode 100644 e2e/react-start/query-integration/tailwind.config.mjs create mode 100644 e2e/react-start/query-integration/tests/app.spec.ts create mode 100644 e2e/react-start/query-integration/tests/fixture.ts create mode 100644 e2e/react-start/query-integration/tsconfig.json create mode 100644 e2e/react-start/query-integration/vite.config.ts diff --git a/e2e/react-start/query-integration/.gitignore b/e2e/react-start/query-integration/.gitignore new file mode 100644 index 0000000000..ca63f49885 --- /dev/null +++ b/e2e/react-start/query-integration/.gitignore @@ -0,0 +1,18 @@ +node_modules +package-lock.json +yarn.lock + +.DS_Store +.cache +.env +.vercel +.output +/build/ +/api/ +/server/build +/public/build# Sentry Config File +.env.sentry-build-plugin +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/e2e/react-start/query-integration/.prettierignore b/e2e/react-start/query-integration/.prettierignore new file mode 100644 index 0000000000..2be5eaa6ec --- /dev/null +++ b/e2e/react-start/query-integration/.prettierignore @@ -0,0 +1,4 @@ +**/build +**/public +pnpm-lock.yaml +routeTree.gen.ts \ No newline at end of file diff --git a/e2e/react-start/query-integration/package.json b/e2e/react-start/query-integration/package.json new file mode 100644 index 0000000000..fca0338c77 --- /dev/null +++ b/e2e/react-start/query-integration/package.json @@ -0,0 +1,39 @@ +{ + "name": "tanstack-react-start-e2e-query-integration", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "node .output/server/index.mjs", + "test:e2e": "playwright test --project=chromium" + }, + "dependencies": { + "@tanstack/react-query": "^5.66.0", + "@tanstack/react-query-devtools": "^5.66.0", + "@tanstack/react-router": "workspace:^", + "@tanstack/react-router-devtools": "workspace:^", + "@tanstack/react-router-ssr-query": "workspace:^", + "@tanstack/react-start": "workspace:^", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwind-merge": "^2.6.0", + "vite": "^6.3.5", + "zod": "^3.24.2" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "@types/node": "^22.10.2", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.5.1", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.2", + "vite-tsconfig-paths": "^5.1.4" + } +} diff --git a/e2e/react-start/query-integration/playwright.config.ts b/e2e/react-start/query-integration/playwright.config.ts new file mode 100644 index 0000000000..9806e0c136 --- /dev/null +++ b/e2e/react-start/query-integration/playwright.config.ts @@ -0,0 +1,34 @@ +import { defineConfig, devices } from '@playwright/test' +import { derivePort } from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = derivePort(packageJson.name) +const baseURL = `http://localhost:${PORT}` +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + workers: 1, + + reporter: [['line']], + + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL, + }, + + webServer: { + command: `VITE_SERVER_PORT=${PORT} pnpm build && PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start`, + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + }, + + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], +}) diff --git a/e2e/react-start/query-integration/postcss.config.mjs b/e2e/react-start/query-integration/postcss.config.mjs new file mode 100644 index 0000000000..2e7af2b7f1 --- /dev/null +++ b/e2e/react-start/query-integration/postcss.config.mjs @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/e2e/react-start/query-integration/src/queryOptions.ts b/e2e/react-start/query-integration/src/queryOptions.ts new file mode 100644 index 0000000000..e03175c999 --- /dev/null +++ b/e2e/react-start/query-integration/src/queryOptions.ts @@ -0,0 +1,15 @@ +import { queryOptions } from "@tanstack/react-query" + +export const makeQueryOptions = (key: string) => queryOptions({ + queryKey: ['e2e-test-query-integration', key], + queryFn: async () => { + console.log('fetching query data') + await new Promise((resolve) => { + setTimeout(resolve, 500) + }) + const result = typeof window !== 'undefined' ? 'client' : 'server' + console.log('query data result', result) + return result + }, + staleTime: Infinity, + }) \ No newline at end of file diff --git a/e2e/react-start/query-integration/src/routeTree.gen.ts b/e2e/react-start/query-integration/src/routeTree.gen.ts new file mode 100644 index 0000000000..e98a780a1e --- /dev/null +++ b/e2e/react-start/query-integration/src/routeTree.gen.ts @@ -0,0 +1,122 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as UseSuspenseQueryRouteImport } from './routes/useSuspenseQuery' +import { Route as UseQueryRouteImport } from './routes/useQuery' +import { Route as IndexRouteImport } from './routes/index' +import { Route as LoaderFetchQueryTypeRouteImport } from './routes/loader-fetchQuery/$type' + +const UseSuspenseQueryRoute = UseSuspenseQueryRouteImport.update({ + id: '/useSuspenseQuery', + path: '/useSuspenseQuery', + getParentRoute: () => rootRouteImport, +} as any) +const UseQueryRoute = UseQueryRouteImport.update({ + id: '/useQuery', + path: '/useQuery', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const LoaderFetchQueryTypeRoute = LoaderFetchQueryTypeRouteImport.update({ + id: '/loader-fetchQuery/$type', + path: '/loader-fetchQuery/$type', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/useQuery': typeof UseQueryRoute + '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/loader-fetchQuery/$type': typeof LoaderFetchQueryTypeRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/useQuery': typeof UseQueryRoute + '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/loader-fetchQuery/$type': typeof LoaderFetchQueryTypeRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/useQuery': typeof UseQueryRoute + '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/loader-fetchQuery/$type': typeof LoaderFetchQueryTypeRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '/useQuery' + | '/useSuspenseQuery' + | '/loader-fetchQuery/$type' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/useQuery' | '/useSuspenseQuery' | '/loader-fetchQuery/$type' + id: + | '__root__' + | '/' + | '/useQuery' + | '/useSuspenseQuery' + | '/loader-fetchQuery/$type' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + UseQueryRoute: typeof UseQueryRoute + UseSuspenseQueryRoute: typeof UseSuspenseQueryRoute + LoaderFetchQueryTypeRoute: typeof LoaderFetchQueryTypeRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/useSuspenseQuery': { + id: '/useSuspenseQuery' + path: '/useSuspenseQuery' + fullPath: '/useSuspenseQuery' + preLoaderRoute: typeof UseSuspenseQueryRouteImport + parentRoute: typeof rootRouteImport + } + '/useQuery': { + id: '/useQuery' + path: '/useQuery' + fullPath: '/useQuery' + preLoaderRoute: typeof UseQueryRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/loader-fetchQuery/$type': { + id: '/loader-fetchQuery/$type' + path: '/loader-fetchQuery/$type' + fullPath: '/loader-fetchQuery/$type' + preLoaderRoute: typeof LoaderFetchQueryTypeRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + UseQueryRoute: UseQueryRoute, + UseSuspenseQueryRoute: UseSuspenseQueryRoute, + LoaderFetchQueryTypeRoute: LoaderFetchQueryTypeRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() diff --git a/e2e/react-start/query-integration/src/router.tsx b/e2e/react-start/query-integration/src/router.tsx new file mode 100644 index 0000000000..e30458c549 --- /dev/null +++ b/e2e/react-start/query-integration/src/router.tsx @@ -0,0 +1,25 @@ +import { QueryClient } from '@tanstack/react-query' +import { createRouter as createTanStackRouter } from '@tanstack/react-router' +import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query' +import { routeTree } from './routeTree.gen' + +export function createRouter() { + const queryClient = new QueryClient() + const router = createTanStackRouter({ + routeTree, + context: { queryClient }, + scrollRestoration: true, + defaultPreload: 'intent', + }) + setupRouterSsrQueryIntegration({ + router, + queryClient, + }) + return router +} + +declare module '@tanstack/react-router' { + interface Register { + router: ReturnType + } +} diff --git a/e2e/react-start/query-integration/src/routes/__root.tsx b/e2e/react-start/query-integration/src/routes/__root.tsx new file mode 100644 index 0000000000..3f887f9491 --- /dev/null +++ b/e2e/react-start/query-integration/src/routes/__root.tsx @@ -0,0 +1,87 @@ +/// +import { + HeadContent, + Link, + Scripts, + createRootRouteWithContext, +} from '@tanstack/react-router' +import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import { TanStackRouterDevtoolsInProd } from '@tanstack/react-router-devtools' +import * as React from 'react' +import type { QueryClient } from '@tanstack/react-query' +import appCss from '~/styles/app.css?url' + +export const Route = createRootRouteWithContext<{ + queryClient: QueryClient +}>()({ + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + ], + links: [{ rel: 'stylesheet', href: appCss }], + }), + shellComponent: RootDocument, +}) + +function RootDocument({ children }: { children: React.ReactNode }) { + return ( + + + + + +
+ + Home + {' '} + + fetchQuery (sync) + {' '} + + fetchQuery (async) + {' '} + + useQuery + {' '} + + useSuspenseQuery + {' '} +
+
+ {children} + + + + + + ) +} diff --git a/e2e/react-start/query-integration/src/routes/index.tsx b/e2e/react-start/query-integration/src/routes/index.tsx new file mode 100644 index 0000000000..5f749a7821 --- /dev/null +++ b/e2e/react-start/query-integration/src/routes/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/')({ + component: Home, +}) + +function Home() { + return ( +
+

Query Integration E2E tests

+
+ ) +} diff --git a/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx b/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx new file mode 100644 index 0000000000..adc0e64334 --- /dev/null +++ b/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx @@ -0,0 +1,43 @@ +import { useQuery } from '@tanstack/react-query' +import { createFileRoute } from '@tanstack/react-router' +import z from 'zod' +import { makeQueryOptions } from '~/queryOptions' + + +export const Route = createFileRoute('/loader-fetchQuery/$type')({ + component: RouteComponent, + params: { + parse: ({ type }) => + z + .object({ + type: z.union([z.literal('sync'), z.literal('async')]), + }) + .parse({ type }), + }, + context: ({params} ) => ({queryOptions: makeQueryOptions(`loader-fetchQuery-${params.type}`)}), + loader: ({ context, params }) => { + const queryPromise = context.queryClient.fetchQuery(context.queryOptions) + if (params.type === 'sync') { + return queryPromise + } + }, + ssr: 'data-only', +}) + +function RouteComponent() { + const loaderData = Route.useLoaderData() + const context = Route.useRouteContext() + const query = useQuery(context.queryOptions) + return ( +
+
+ loader data:{' '} +
{loaderData ?? 'undefined'}
+
+
+ query data:{' '} +
{query.data ?? 'loading...'}
+
+
+ ) +} diff --git a/e2e/react-start/query-integration/src/routes/useQuery.tsx b/e2e/react-start/query-integration/src/routes/useQuery.tsx new file mode 100644 index 0000000000..223189bda1 --- /dev/null +++ b/e2e/react-start/query-integration/src/routes/useQuery.tsx @@ -0,0 +1,22 @@ +import { useQuery } from '@tanstack/react-query' +import { createFileRoute } from '@tanstack/react-router' +import { makeQueryOptions } from '~/queryOptions' + +const qOptions = makeQueryOptions('useQuery') + +export const Route = createFileRoute('/useQuery')({ + component: RouteComponent, + ssr: true, +}) + +function RouteComponent() { + const query = useQuery(qOptions) + return ( +
+
+ query data:{' '} +
{query.data ?? 'loading...'}
+
+
+ ) +} diff --git a/e2e/react-start/query-integration/src/routes/useSuspenseQuery.tsx b/e2e/react-start/query-integration/src/routes/useSuspenseQuery.tsx new file mode 100644 index 0000000000..4c4ae3a710 --- /dev/null +++ b/e2e/react-start/query-integration/src/routes/useSuspenseQuery.tsx @@ -0,0 +1,20 @@ +import { useSuspenseQuery } from '@tanstack/react-query' +import { createFileRoute } from '@tanstack/react-router' +import { makeQueryOptions } from '~/queryOptions' + +const qOptions = makeQueryOptions('useSuspenseQuery') + +export const Route = createFileRoute('/useSuspenseQuery')({ + component: RouteComponent, +}) + +function RouteComponent() { + const query = useSuspenseQuery(qOptions) + return ( +
+
+ query data:
{query.data}
+
+
+ ) +} diff --git a/e2e/react-start/query-integration/src/styles/app.css b/e2e/react-start/query-integration/src/styles/app.css new file mode 100644 index 0000000000..c53c870665 --- /dev/null +++ b/e2e/react-start/query-integration/src/styles/app.css @@ -0,0 +1,22 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + html { + color-scheme: light dark; + } + + * { + @apply border-gray-200 dark:border-gray-800; + } + + html, + body { + @apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200; + } + + .using-mouse * { + outline: none !important; + } +} diff --git a/e2e/react-start/query-integration/tailwind.config.mjs b/e2e/react-start/query-integration/tailwind.config.mjs new file mode 100644 index 0000000000..e49f4eb776 --- /dev/null +++ b/e2e/react-start/query-integration/tailwind.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{js,jsx,ts,tsx}'], +} diff --git a/e2e/react-start/query-integration/tests/app.spec.ts b/e2e/react-start/query-integration/tests/app.spec.ts new file mode 100644 index 0000000000..5c78722d20 --- /dev/null +++ b/e2e/react-start/query-integration/tests/app.spec.ts @@ -0,0 +1,48 @@ +import { expect } from '@playwright/test' +import { test } from './fixture' + +// if the query would not be streamed to the client, it would re-execute on the client +// and thus cause a hydration mismatch since the query function returns 'client' when executed on the client +test.describe('queries are streamed from the server', () => { + test('direct visit - loader on server runs fetchQuery and awaits it', async ({ + page, + }) => { + await page.goto('/loader-fetchQuery/sync') + + // wait for the query data to be streamed from the server + const queryData = page.getByTestId('query-data') + await expect(queryData).toHaveText('server') + + // the loader data should be the same as the query data + const loaderData = page.getByTestId('loader-data') + await expect(loaderData).toHaveText('server') + }) + test('direct visit - loader on server runs fetchQuery and does not await it', async ({ + page, + }) => { + await page.goto('/loader-fetchQuery/async') + + // wait for the query data to be streamed from the server + const queryData = page.getByTestId('query-data') + await expect(queryData).toHaveText('server') + + const loaderData = page.getByTestId('loader-data') + await expect(loaderData).toHaveText('undefined') + }) + + test('useSuspenseQuery', async ({ page }) => { + await page.goto('/useSuspenseQuery') + + const queryData = page.getByTestId('query-data') + await expect(queryData).toHaveText('server') + }) +}) + +test('useQuery does not execute on the server and therefore does not stream data to the client', async ({ + page, +}) => { + await page.goto('/useQuery') + + const queryData = page.getByTestId('query-data') + await expect(queryData).toHaveText('client') +}) diff --git a/e2e/react-start/query-integration/tests/fixture.ts b/e2e/react-start/query-integration/tests/fixture.ts new file mode 100644 index 0000000000..abb7b1d564 --- /dev/null +++ b/e2e/react-start/query-integration/tests/fixture.ts @@ -0,0 +1,28 @@ +import { test as base, expect } from '@playwright/test' + +export interface TestFixtureOptions { + whitelistErrors: Array +} +export const test = base.extend({ + whitelistErrors: [[], { option: true }], + page: async ({ page, whitelistErrors }, use) => { + const errorMessages: Array = [] + page.on('console', (m) => { + if (m.type() === 'error') { + const text = m.text() + for (const whitelistError of whitelistErrors) { + if ( + (typeof whitelistError === 'string' && + text.includes(whitelistError)) || + (whitelistError instanceof RegExp && whitelistError.test(text)) + ) { + return + } + } + errorMessages.push(text) + } + }) + await use(page) + expect(errorMessages).toEqual([]) + }, +}) diff --git a/e2e/react-start/query-integration/tsconfig.json b/e2e/react-start/query-integration/tsconfig.json new file mode 100644 index 0000000000..3a9fb7cd71 --- /dev/null +++ b/e2e/react-start/query-integration/tsconfig.json @@ -0,0 +1,22 @@ +{ + "include": ["**/*.ts", "**/*.tsx"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ES2022", + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./src/*"] + }, + "noEmit": true + } +} diff --git a/e2e/react-start/query-integration/vite.config.ts b/e2e/react-start/query-integration/vite.config.ts new file mode 100644 index 0000000000..1df337cd40 --- /dev/null +++ b/e2e/react-start/query-integration/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' +import tsConfigPaths from 'vite-tsconfig-paths' +import { tanstackStart } from '@tanstack/react-start/plugin/vite' + +export default defineConfig({ + plugins: [ + tsConfigPaths({ + projects: ['./tsconfig.json'], + }), + tanstackStart(), + ], +}) diff --git a/packages/router-ssr-query-core/src/index.ts b/packages/router-ssr-query-core/src/index.ts index f91f8d7b88..a692c8c28f 100644 --- a/packages/router-ssr-query-core/src/index.ts +++ b/packages/router-ssr-query-core/src/index.ts @@ -23,7 +23,7 @@ export type RouterSsrQueryOptions = { } type DehydratedRouterQueryState = { - dehydratedQueryClient: QueryDehydratedState + dehydratedQueryClient?: QueryDehydratedState queryStream: ReadableStream } @@ -36,22 +36,28 @@ export function setupCoreRouterSsrQueryIntegration({ const ogDehydrate = router.options.dehydrate if (router.isServer) { + const sentQueries = new Set() const queryStream = createPushableStream() router.options.dehydrate = async (): Promise => { router.serverSsr!.onRenderFinished(() => queryStream.close()) const ogDehydrated = await ogDehydrate?.() - const dehydratedQueryClient = queryDehydrate(queryClient) const dehydratedRouter = { ...ogDehydrated, - // When critical data is dehydrated, we also dehydrate the query client - dehydratedQueryClient, // prepare the stream for queries coming up during rendering queryStream: queryStream.stream, } + const dehydratedQueryClient = queryDehydrate(queryClient) + if (dehydratedQueryClient.queries.length > 0) { + dehydratedQueryClient.queries.forEach((query) => { + sentQueries.add(query.queryHash) + }) + dehydratedRouter.dehydratedQueryClient = dehydratedQueryClient + } + return dehydratedRouter } @@ -65,41 +71,49 @@ export function setupCoreRouterSsrQueryIntegration({ }) queryClient.getQueryCache().subscribe((event) => { - if (event.type === 'added') { - // before rendering starts, we do not stream individual queries - // instead we dehydrate the entire query client in router's dehydrate() - // if attachRouterServerSsrUtils() has not been called yet, `router.serverSsr` will be undefined and we also do not stream - if (!router.serverSsr?.isDehydrated()) { - return - } - if (queryStream.isClosed()) { - console.warn( - `tried to stream query ${event.query.queryHash} after stream was already closed`, - ) - return - } - queryStream.enqueue( - queryDehydrate(queryClient, { - shouldDehydrateQuery: (query) => { - if (query.queryHash === event.query.queryHash) { - return ( - ogClientOptions.dehydrate?.shouldDehydrateQuery?.(query) ?? - true - ) - } - return false - }, - }), + // before rendering starts, we do not stream individual queries + // instead we dehydrate the entire query client in router's dehydrate() + // if attachRouterServerSsrUtils() has not been called yet, `router.serverSsr` will be undefined and we also do not stream + if (!router.serverSsr?.isDehydrated()) { + return + } + if (sentQueries.has(event.query.queryHash)) { + return + } + if (queryStream.isClosed()) { + console.warn( + `tried to stream query ${event.query.queryHash} after stream was already closed`, ) + return } + // promise not yet set on the query, so we cannot stream it yet + if (!event.query.promise) { + return + } + sentQueries.add(event.query.queryHash) + queryStream.enqueue( + queryDehydrate(queryClient, { + shouldDehydrateQuery: (query) => { + if (query.queryHash === event.query.queryHash) { + return ( + ogClientOptions.dehydrate?.shouldDehydrateQuery?.(query) ?? true + ) + } + return false + }, + }), + ) }) // on the client } else { router.options.hydrate = async (dehydrated: DehydratedRouterQueryState) => { await ogHydrate?.(dehydrated) - // On the client, hydrate the query client with the dehydrated data - queryHydrate(queryClient, dehydrated.dehydratedQueryClient) + // hydrate the query client with the dehydrated data (if it was dehydrated on the server) + if (dehydrated.dehydratedQueryClient) { + queryHydrate(queryClient, dehydrated.dehydratedQueryClient) + } + // read the query stream and hydrate the queries as they come in const reader = dehydrated.queryStream.getReader() reader .read() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdaef034f3..5fb14a08ec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1297,6 +1297,76 @@ importers: specifier: ^5.1.4 version: 5.1.4(typescript@5.8.2)(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) + e2e/react-start/query-integration: + dependencies: + '@tanstack/react-query': + specifier: 5.66.0 + version: 5.66.0(react@19.0.0) + '@tanstack/react-query-devtools': + specifier: ^5.66.0 + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + '@tanstack/react-router': + specifier: workspace:* + version: link:../../../packages/react-router + '@tanstack/react-router-devtools': + specifier: workspace:^ + version: link:../../../packages/react-router-devtools + '@tanstack/react-router-ssr-query': + specifier: workspace:* + version: link:../../../packages/react-router-ssr-query + '@tanstack/react-start': + specifier: workspace:* + version: link:../../../packages/react-start + react: + specifier: ^19.0.0 + version: 19.0.0 + react-dom: + specifier: ^19.0.0 + version: 19.0.0(react@19.0.0) + tailwind-merge: + specifier: ^2.6.0 + version: 2.6.0 + vite: + specifier: 6.3.5 + version: 6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0) + zod: + specifier: ^3.24.2 + version: 3.25.57 + devDependencies: + '@playwright/test': + specifier: ^1.52.0 + version: 1.52.0 + '@tanstack/router-e2e-utils': + specifier: workspace:^ + version: link:../../e2e-utils + '@types/node': + specifier: ^22.10.2 + version: 22.13.4 + '@types/react': + specifier: ^19.0.8 + version: 19.0.8 + '@types/react-dom': + specifier: ^19.0.3 + version: 19.0.3(@types/react@19.0.8) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.6.0(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.5.3) + postcss: + specifier: ^8.5.1 + version: 8.5.3 + tailwindcss: + specifier: ^3.4.17 + version: 3.4.17 + typescript: + specifier: ^5.7.2 + version: 5.8.3 + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.7.0)) + e2e/react-start/scroll-restoration: dependencies: '@tanstack/react-router': From 363fc049e6589f8d2873800596836c806d5bb837 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 20:23:53 +0000 Subject: [PATCH 11/11] ci: apply automated fixes --- e2e/react-start/query-integration/src/queryOptions.ts | 7 ++++--- .../src/routes/loader-fetchQuery/$type.tsx | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/e2e/react-start/query-integration/src/queryOptions.ts b/e2e/react-start/query-integration/src/queryOptions.ts index e03175c999..6ddbb8fed5 100644 --- a/e2e/react-start/query-integration/src/queryOptions.ts +++ b/e2e/react-start/query-integration/src/queryOptions.ts @@ -1,6 +1,7 @@ -import { queryOptions } from "@tanstack/react-query" +import { queryOptions } from '@tanstack/react-query' -export const makeQueryOptions = (key: string) => queryOptions({ +export const makeQueryOptions = (key: string) => + queryOptions({ queryKey: ['e2e-test-query-integration', key], queryFn: async () => { console.log('fetching query data') @@ -12,4 +13,4 @@ export const makeQueryOptions = (key: string) => queryOptions({ return result }, staleTime: Infinity, - }) \ No newline at end of file + }) diff --git a/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx b/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx index adc0e64334..cc5de34e91 100644 --- a/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx +++ b/e2e/react-start/query-integration/src/routes/loader-fetchQuery/$type.tsx @@ -3,7 +3,6 @@ import { createFileRoute } from '@tanstack/react-router' import z from 'zod' import { makeQueryOptions } from '~/queryOptions' - export const Route = createFileRoute('/loader-fetchQuery/$type')({ component: RouteComponent, params: { @@ -14,7 +13,9 @@ export const Route = createFileRoute('/loader-fetchQuery/$type')({ }) .parse({ type }), }, - context: ({params} ) => ({queryOptions: makeQueryOptions(`loader-fetchQuery-${params.type}`)}), + context: ({ params }) => ({ + queryOptions: makeQueryOptions(`loader-fetchQuery-${params.type}`), + }), loader: ({ context, params }) => { const queryPromise = context.queryClient.fetchQuery(context.queryOptions) if (params.type === 'sync') {