- 新增 queryKeys.ts 统一 QueryKey 工厂(覆盖全部模块,invalidate/refetch/prefetch 同源) - 新增 queryClient.ts 全局配置:retry 1、staleTime 30s、gcTime 5min、refetchOnWindowFocus false - 新增 useApiQuery:zod schema 校验 + 类型收敛 + select 转换,消除页面重复 validateResponse 样板 - useApiMutation 支持 onMutate/onSettled/context(乐观更新) - 示范迁移:Organizations(useApiQuery + 乐观更新归档/恢复)、Students(useApiQuery + queryKeys + 打开抽屉前 prefetch 档案聚合) - StudentProfileContent queryKey 统一为 queryKeys.archive.detail,prefetch 可命中缓存
32 lines
1.1 KiB
TypeScript
32 lines
1.1 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
||
import type { QueryKey } from '@tanstack/react-query';
|
||
import type { z } from 'zod';
|
||
import { validateResponse } from '../utils/validate';
|
||
|
||
interface UseApiQueryOptions<T, TSelected = T> {
|
||
queryKey: QueryKey;
|
||
queryFn: () => Promise<unknown>;
|
||
/** zod schema:响应校验失败会抛出带字段路径的错误,由统一错误处理展示 */
|
||
schema: z.ZodType<unknown>;
|
||
enabled?: boolean;
|
||
staleTime?: number;
|
||
/** 可选的数据转换(React Query select),例如列表原始行 → UI 模型 */
|
||
select?: (data: T) => TSelected;
|
||
}
|
||
|
||
/**
|
||
* useQuery 的类型安全封装:queryFn 返回 unknown,
|
||
* 由 zod schema 校验并收敛为 T,消除各页面重复的
|
||
* `validateResponse(schema, await api.get(...))` 样板。
|
||
*/
|
||
export function useApiQuery<T, TSelected = T>(options: UseApiQueryOptions<T, TSelected>) {
|
||
const { queryKey, queryFn, schema, enabled, staleTime, select } = options;
|
||
return useQuery<T, Error, TSelected>({
|
||
queryKey,
|
||
enabled,
|
||
staleTime,
|
||
queryFn: async () => validateResponse<T>(schema, await queryFn()),
|
||
select,
|
||
});
|
||
}
|