TanStack Query中useQuery的onSuccess与select选项差异及类型推导问题
TanStack Query useQuery 相关问题解答
1. onSuccess 与 select 选项的区别
- 核心作用不同
select是数据转换层:专注于对queryFn返回的原始数据做同步加工,输出组件实际需要的数据格式,最终useQuery返回的data就是转换后的值,但缓存中存储的仍是原始数据。onSuccess是成功回调钩子:用于在请求成功完成后执行副作用逻辑,比如弹出成功提示、更新全局状态、跳转路由等,不参与数据的转换或缓存操作。
- 缓存交互逻辑不同
select不会修改缓存内的原始数据,同一 Query Key 下的其他组件若未配置select,获取到的还是原始请求结果。onSuccess与缓存数据无直接关联,仅作为请求成功后的触发点执行额外操作。
- 执行时机与返回值
select每次从缓存或新请求中获取数据时都会执行,其返回值会覆盖原始数据作为组件可用的data。onSuccess仅在新请求成功完成时触发(从缓存读取数据不会触发),无返回值,仅负责执行副作用。
2. select 选项的类型推导问题
不需要在转换后显式添加类型,TanStack Query 支持通过自动推导或显式泛型指定两种方式获取转换后的类型:
- 自动推导:只要
select函数的返回类型明确,TypeScript 会自动将useQuery返回的data类型识别为转换后的值。示例:interface User { id: number; name: string; } const { data } = useQuery({ queryKey: ['users'], queryFn: () => fetch('/api/users').then(res => res.json() as User[]), select: (users) => users.map(user => user.name) // 返回 string[] 类型 }); // data 自动推导为 string[] - 显式指定泛型:如果转换逻辑复杂导致自动推导失效,可通过
useQuery的泛型参数明确最终数据类型、原始数据类型和错误类型:interface User { id: number; name: string; } type UserNameList = string[]; const { data } = useQuery<UserNameList, Error, User[]>({ queryKey: ['users'], queryFn: () => fetch('/api/users').then(res => res.json() as User[]), select: (users) => users.map(user => user.name) }); // data 类型为 UserNameList - 特殊情况:若
select函数存在多分支逻辑导致返回类型模糊,可给select函数添加返回类型注解,进一步明确类型,无需手动转换后再额外赋值类型。
内容的提问来源于stack exchange,提问作者choisuhyeok
相关产品推荐
相关产品推荐

