如何区分React Query中initialData与后续获取的完整数据?
区分React Query中initialData与完整请求数据的实现方案
你当前的代码用initialData从localStorage获取了精简的用户数据,但需要区分这部分初始数据和后端返回的完整数据,下面是几种可行的实现方式:
1. 给数据添加自定义标识字段
直接在初始数据里加一个后端不会返回的标记字段,比如isInitialData,这样就能直观区分两种数据:
export const useCurrentUser = () => { const enabled = !isGuestUser(); return useQuery({ queryKey: ['currentUser'], queryFn: async () => { const fullUser = await getCurrentUser(); // 给完整数据加上标记,明确不是初始数据 return { ...fullUser, isInitialData: false }; }, gcTime: Infinity, initialData: enabled ? // 给初始数据加上专属标记 { ...(jwtDecode(localStorage.getItem('token') as string) as User), isInitialData: true } : { ...({} as User), isInitialData: true }, enabled, refetchOnWindowFocus: false, }); };
使用时直接通过data.isInitialData判断即可,TypeScript也能自动识别这个字段的存在。
2. 利用React Query自带的状态字段
React Query返回的结果里有几个状态字段可以辅助判断:
isFetching:当正在请求完整数据时为true,请求完成后变为falsedataUpdatedAt:初始数据的更新时间是组件挂载时的时间,完整数据返回后这个时间会被更新
示例用法:
const { data, dataUpdatedAt, isFetching } = useCurrentUser(); // 记录初始时间,用来对比判断是否是初始数据 const initialTime = useRef(Date.now()); const isInitialData = dataUpdatedAt === initialTime.current;
如果是React Query v4及以上版本,还可以用isInitialLoading字段,它会在首次请求(包括使用initialData的阶段)完成后变为false,后续缓存命中时不会触发。
针对TypeScript类型的补充处理
你提到用placeholderData会让类型变成User | undefined,而initialData能保持User类型。可以结合上面的标识字段定义联合类型,让TypeScript自动区分数据类型:
// 定义初始数据和完整数据的类型 type InitialUser = User & { isInitialData: true }; type FullUser = User & { isInitialData: false }; type CurrentUser = InitialUser | FullUser; export const useCurrentUser = () => { const enabled = !isGuestUser(); return useQuery<CurrentUser>({ queryKey: ['currentUser'], queryFn: async () => { const fullUser = await getCurrentUser(); return { ...fullUser, isInitialData: false }; }, gcTime: Infinity, initialData: enabled ? { ...(jwtDecode(localStorage.getItem('token') as string) as User), isInitialData: true } : { ...({} as User), isInitialData: true }, enabled, refetchOnWindowFocus: false, }); };
这样在使用data时,TypeScript会根据isInitialData的值自动推断数据的具体类型,避免类型歧义。
内容的提问来源于stack exchange,提问作者Korer
相关产品推荐
相关产品推荐

