在RTK Query中用Zod Schema验证API响应:位置与函数选择
用Zod验证RTK Query的API响应
验证该放在哪?
RTK Query的builder.query里有个transformResponse钩子,这就是处理API响应、做验证最合适的地方——数据存入Redux前就能完成校验,不会把脏数据塞到状态里。
parse还是safeParse?
- parse:如果API返回的数据不符合Schema,直接抛错,触发RTK Query的错误状态(比如
isError)。适合你确定API格式严格靠谱,或者希望不合规数据直接报错的场景。 - safeParse:不会抛错,返回一个带
success字段的对象。适合需要自定义错误处理的情况,比如打个日志、返回默认值,不让整个请求失败。
代码示例
用parse的写法
import { z } from 'zod'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const userSchema = z.object({ id: z.string(), name: z.string(), age: z.number(), }); type User = z.infer<typeof userSchema>; export const userAPI = createApi({ reducerPath: 'userAPI', baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }), endpoints: (builder) => ({ getUserById: builder.query<User, string>({ // 注意这里是大写的User,原代码小写写错了 query: (id) => `user/${id}`, transformResponse: (response: unknown) => { // 直接用parse验证,不合规就抛错 return userSchema.parse(response); }, }), }), });
用safeParse的写法
import { z } from 'zod'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; const userSchema = z.object({ id: z.string(), name: z.string(), age: z.number(), }); type User = z.infer<typeof userSchema>; export const userAPI = createApi({ reducerPath: 'userAPI', baseQuery: fetchBaseQuery({ baseUrl: 'https://some-api/' }), endpoints: (builder) => ({ getUserById: builder.query<User | null, string>({ // 类型加个null,处理验证失败的情况 query: (id) => `user/${id}`, transformResponse: (response: unknown) => { const validationResult = userSchema.safeParse(response); if (validationResult.success) { return validationResult.data; } else { // 自定义处理:打日志、返回null或者默认用户对象 console.error('用户数据验证失败:', validationResult.error); return null; } }, }), }), });
小提醒
- 原代码里的
builder.query<user, string>是笔误,要改成User(对应你定义的类型)。 - 如果是获取多个用户,直接用
userSchema.array()来验证整个响应数组就行。
内容的提问来源于stack exchange,提问作者Tanmay Bindal
相关产品推荐
相关产品推荐

