feat(query): integrate @tanstack/react-query for improved data fetching and state management
This commit is contained in:
23
AGENTS.md
23
AGENTS.md
@@ -25,19 +25,36 @@ src/
|
||||
```
|
||||
pages/page-app/
|
||||
├── components/ # 模块专属组件
|
||||
├── store/ # 模块状态管理
|
||||
└── module/ # 模块功能函数
|
||||
├── hooks/ # 模块 React Query hooks(API 查询封装)
|
||||
├── modules/ # 模块功能函数(UI 组件、工具函数等)
|
||||
└── store/ # 模块状态管理(Zustand)
|
||||
```
|
||||
|
||||
### hooks/ 文件夹说明
|
||||
|
||||
每个模块的 `hooks/` 文件夹用于封装与该模块相关的 React Query hooks:
|
||||
|
||||
- **use-api-query.ts**: 使用 `@tanstack/react-query` 的 `useQuery` 封装 API 调用
|
||||
- 定义 `queryKeys` 常量用于缓存标识
|
||||
- 封装 `useQuery` hooks 用于数据获取(GET 请求)
|
||||
- 封装 `useMutation` hooks 用于数据修改(POST/PUT/DELETE 请求)
|
||||
- 支持预取(prefetch)和无限滚动(infinite query)
|
||||
- **index.ts**: 导出模块所有 hooks,便于统一导入使用
|
||||
|
||||
### 状态和数据获取
|
||||
|
||||
- **@tanstack/react-query** 用于数据获取、缓存和状态管理
|
||||
- 在模块的 `hooks/` 文件夹中封装 API 调用
|
||||
- QueryClient 实例位于 `src/modules/query.ts`
|
||||
- 在 `src/routes/__root.tsx` 中通过 `QueryClientProvider` 提供
|
||||
- **Zustand** 用于全局状态管理
|
||||
- **@kevisual/query** 用于数据获取(QueryClient 实例位于 `src/modules/query.ts`)
|
||||
- **@kevisual/query** 用于底层 API 请求封装
|
||||
- **React Hook Form** 用于表单管理
|
||||
|
||||
## 核心依赖
|
||||
|
||||
- **@base-ui/react**: Headless UI 基础组件
|
||||
- **@tanstack/react-query**: 数据获取、缓存和状态管理(配合 hooks/ 使用)
|
||||
- **@tanstack/react-router**: 基于 TanStack Router 插件的文件路由
|
||||
- **class-variance-authority**: 基于变体的样式系统
|
||||
- **clsx + tailwind-merge**: 通过 `cn()` 提供 className 工具函数
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"@kevisual/api": "^0.0.60",
|
||||
"@kevisual/context": "^0.0.8",
|
||||
"@kevisual/router": "0.0.84",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@tanstack/react-router": "^1.163.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -46,8 +47,8 @@
|
||||
"@kevisual/types": "^0.0.12",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@tanstack/react-router-devtools": "^1.163.3",
|
||||
"@tanstack/router-plugin": "^1.163.3",
|
||||
"@types/node": "^25.3.2",
|
||||
"@tanstack/router-plugin": "^1.164.0",
|
||||
"@types/node": "^25.3.3",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
|
||||
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
@@ -20,6 +20,9 @@ importers:
|
||||
'@kevisual/router':
|
||||
specifier: 0.0.84
|
||||
version: 0.0.84
|
||||
'@tanstack/react-query':
|
||||
specifier: ^5.90.21
|
||||
version: 5.90.21(react@19.2.4)
|
||||
'@tanstack/react-router':
|
||||
specifier: ^1.163.3
|
||||
version: 1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -77,16 +80,16 @@ importers:
|
||||
version: 0.0.12
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
version: 4.2.1(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
'@tanstack/react-router-devtools':
|
||||
specifier: ^1.163.3
|
||||
version: 1.163.3(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.163.3)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@tanstack/router-plugin':
|
||||
specifier: ^1.163.3
|
||||
version: 1.163.3(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
specifier: ^1.164.0
|
||||
version: 1.164.0(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
'@types/node':
|
||||
specifier: ^25.3.2
|
||||
version: 25.3.2
|
||||
specifier: ^25.3.3
|
||||
version: 25.3.3
|
||||
'@types/react':
|
||||
specifier: ^19.2.14
|
||||
version: 19.2.14
|
||||
@@ -95,7 +98,7 @@ importers:
|
||||
version: 19.2.3(@types/react@19.2.14)
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^5.1.4
|
||||
version: 5.1.4(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
version: 5.1.4(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))
|
||||
dotenv:
|
||||
specifier: ^17.3.1
|
||||
version: 17.3.1
|
||||
@@ -113,7 +116,7 @@ importers:
|
||||
version: 5.9.3
|
||||
vite:
|
||||
specifier: v8.0.0-beta.15
|
||||
version: 8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
version: 8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -853,6 +856,14 @@ packages:
|
||||
resolution: {integrity: sha512-Kp/WSt411ZWYvgXy6uiv5RmhHrz9cAml05AQPrtdAp7eUqvIDbMGPnML25OKbzR3RJ1q4wgENxDTvlGPa9+Mww==}
|
||||
engines: {node: '>=20.19'}
|
||||
|
||||
'@tanstack/query-core@5.90.20':
|
||||
resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==}
|
||||
|
||||
'@tanstack/react-query@5.90.21':
|
||||
resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==}
|
||||
peerDependencies:
|
||||
react: ^18 || ^19
|
||||
|
||||
'@tanstack/react-router-devtools@1.163.3':
|
||||
resolution: {integrity: sha512-42VMkV/2Z8ro7xzblPBRNZIEmCNXMzm2jD68G52p2qhjXm38wGpg46qneAESN9FtTQeVWk5aSXs47/jt7lkzmw==}
|
||||
engines: {node: '>=20.19'}
|
||||
@@ -892,12 +903,12 @@ packages:
|
||||
csstype:
|
||||
optional: true
|
||||
|
||||
'@tanstack/router-generator@1.163.3':
|
||||
resolution: {integrity: sha512-i2rWRtqY/yCYUDXva1li4zeDP20oFjMt/wh9RnGJCrKSLWrvEGnxAOSyXgiOsoJnU96TTQ0mUDbGfXsSTupeZQ==}
|
||||
'@tanstack/router-generator@1.164.0':
|
||||
resolution: {integrity: sha512-Uiyj+RtW0kdeqEd8NEd3Np1Z2nhJ2xgLS8U+5mTvFrm/s3xkM2LYjJHoLzc6am7sKPDsmeF9a4/NYq3R7ZJP0Q==}
|
||||
engines: {node: '>=20.19'}
|
||||
|
||||
'@tanstack/router-plugin@1.163.3':
|
||||
resolution: {integrity: sha512-JOUYuUX2N9ZHnmkmvmiGzXGbkvrur/5BfW/+vpiZzuifSyvdc0XsfwkTpjvwWx9ymp4ZshSVKiQQKQi09YweIw==}
|
||||
'@tanstack/router-plugin@1.164.0':
|
||||
resolution: {integrity: sha512-cZPsEMhqzyzmuPuDbsTAzBZaT+cj0pGjwdhjxJfPCM06Ax8v4tFR7n/Ug0UCwnNAUEmKZWN3lA9uT+TxXnk9PQ==}
|
||||
engines: {node: '>=20.19'}
|
||||
peerDependencies:
|
||||
'@rsbuild/core': '>=1.0.2'
|
||||
@@ -943,8 +954,8 @@ packages:
|
||||
'@types/babel__traverse@7.28.0':
|
||||
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
|
||||
|
||||
'@types/node@25.3.2':
|
||||
resolution: {integrity: sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q==}
|
||||
'@types/node@25.3.3':
|
||||
resolution: {integrity: sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==}
|
||||
|
||||
'@types/react-dom@19.2.3':
|
||||
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
|
||||
@@ -2169,15 +2180,22 @@ snapshots:
|
||||
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.1
|
||||
'@tailwindcss/oxide-win32-x64-msvc': 4.2.1
|
||||
|
||||
'@tailwindcss/vite@4.2.1(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
'@tailwindcss/vite@4.2.1(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
dependencies:
|
||||
'@tailwindcss/node': 4.2.1
|
||||
'@tailwindcss/oxide': 4.2.1
|
||||
tailwindcss: 4.2.1
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
|
||||
'@tanstack/history@1.161.4': {}
|
||||
|
||||
'@tanstack/query-core@5.90.20': {}
|
||||
|
||||
'@tanstack/react-query@5.90.21(react@19.2.4)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.90.20
|
||||
react: 19.2.4
|
||||
|
||||
'@tanstack/react-router-devtools@1.163.3(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@tanstack/router-core@1.163.3)(csstype@3.2.3)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
|
||||
dependencies:
|
||||
'@tanstack/react-router': 1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -2226,7 +2244,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@tanstack/router-generator@1.163.3':
|
||||
'@tanstack/router-generator@1.164.0':
|
||||
dependencies:
|
||||
'@tanstack/router-core': 1.163.3
|
||||
'@tanstack/router-utils': 1.161.4
|
||||
@@ -2239,7 +2257,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@tanstack/router-plugin@1.163.3(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
'@tanstack/router-plugin@1.164.0(@tanstack/react-router@1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0)
|
||||
@@ -2248,7 +2266,7 @@ snapshots:
|
||||
'@babel/traverse': 7.29.0
|
||||
'@babel/types': 7.29.0
|
||||
'@tanstack/router-core': 1.163.3
|
||||
'@tanstack/router-generator': 1.163.3
|
||||
'@tanstack/router-generator': 1.164.0
|
||||
'@tanstack/router-utils': 1.161.4
|
||||
'@tanstack/virtual-file-routes': 1.161.4
|
||||
chokidar: 3.6.0
|
||||
@@ -2256,7 +2274,7 @@ snapshots:
|
||||
zod: 3.25.76
|
||||
optionalDependencies:
|
||||
'@tanstack/react-router': 1.163.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -2304,7 +2322,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.29.0
|
||||
|
||||
'@types/node@25.3.2':
|
||||
'@types/node@25.3.3':
|
||||
dependencies:
|
||||
undici-types: 7.18.2
|
||||
|
||||
@@ -2316,7 +2334,7 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@vitejs/plugin-react@5.1.4(vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
'@vitejs/plugin-react@5.1.4(vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
|
||||
@@ -2324,7 +2342,7 @@ snapshots:
|
||||
'@rolldown/pluginutils': 1.0.0-rc.3
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.18.0
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
vite: 8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -2783,7 +2801,7 @@ snapshots:
|
||||
dependencies:
|
||||
react: 19.2.4
|
||||
|
||||
vite@8.0.0-beta.15(@types/node@25.3.2)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0):
|
||||
vite@8.0.0-beta.15(@types/node@25.3.3)(esbuild@0.27.3)(jiti@2.6.1)(tsx@4.21.0):
|
||||
dependencies:
|
||||
'@oxc-project/runtime': 0.114.0
|
||||
lightningcss: 1.31.1
|
||||
@@ -2792,7 +2810,7 @@ snapshots:
|
||||
rolldown: 1.0.0-rc.5
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 25.3.2
|
||||
'@types/node': 25.3.3
|
||||
esbuild: 0.27.3
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Query, DataOpts } from '@kevisual/query';
|
||||
import { QueryLoginBrowser } from '@kevisual/api/query-login'
|
||||
import { useContextKey } from '@kevisual/context';
|
||||
import { QueryClient } from '@tanstack/react-query';
|
||||
|
||||
export const query = useContextKey('query', new Query({
|
||||
url: '/api/router',
|
||||
}));
|
||||
@@ -11,4 +13,6 @@ export const queryClient = useContextKey('queryClient', new Query({
|
||||
|
||||
export const queryLogin = useContextKey('queryLogin', new QueryLoginBrowser({
|
||||
query: query
|
||||
}));
|
||||
}));
|
||||
|
||||
export const stackQueryClient = useContextKey('stackQueryClient', new QueryClient());
|
||||
@@ -6,6 +6,8 @@ import { AuthProvider } from '@/pages/auth'
|
||||
import { TooltipProvider } from '@/components/ui/tooltip'
|
||||
import { useLayoutStore } from '@/pages/auth/store';
|
||||
import { useShallow } from 'zustand/shallow';
|
||||
import { stackQueryClient } from '@/modules/query'
|
||||
import { QueryClientProvider } from '@tanstack/react-query'
|
||||
import clsx from 'clsx';
|
||||
export const Route = createRootRoute({
|
||||
component: RootComponent,
|
||||
@@ -17,20 +19,22 @@ function RootComponent() {
|
||||
showBaseHeader: state.showBaseHeader,
|
||||
})));
|
||||
return (
|
||||
<div className='h-full overflow-hidden'>
|
||||
<LayoutMain />
|
||||
<AuthProvider mustLogin={true}>
|
||||
<TooltipProvider>
|
||||
<main className={clsx('overflow-auto scrollbar', {
|
||||
'h-[calc(100%-3rem)]': store.showBaseHeader,
|
||||
'h-full': !store.showBaseHeader,
|
||||
})}>
|
||||
<Outlet />
|
||||
</main>
|
||||
</TooltipProvider>
|
||||
</AuthProvider>
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
<Toaster />
|
||||
</div>
|
||||
<QueryClientProvider client={stackQueryClient}>
|
||||
<div className='h-full overflow-hidden'>
|
||||
<LayoutMain />
|
||||
<AuthProvider mustLogin={true}>
|
||||
<TooltipProvider>
|
||||
<main className={clsx('overflow-auto scrollbar', {
|
||||
'h-[calc(100%-3rem)]': store.showBaseHeader,
|
||||
'h-full': !store.showBaseHeader,
|
||||
})}>
|
||||
<Outlet />
|
||||
</main>
|
||||
</TooltipProvider>
|
||||
</AuthProvider>
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
<Toaster />
|
||||
</div>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user