使用React Query useMutation时遭遇TypeScript类型错误求助
问题解决:React Query useMutation 类型错误
错误原因
TypeScript 无法自动推断 useMutation 中 mutationFn 的参数类型,导致 mutate 函数的参数被错误推断为 void,与你传入的表单数据类型不匹配。
解决方案
步骤1:定义明确的类型
从 Zod Schema 中导出表单输入类型,再定义适配 API 的请求类型(因为你把 answers 从字符串转成了数组):
import { z } from 'zod'; // 示例:你的 createPoolSchema 定义(根据实际情况调整) const createPoolSchema = z.object({ question: z.string(), answers: z.string(), // 表单中为逗号分隔的字符串 expiresAt: z.date(), isPublic: z.boolean(), }); // 导出表单输入的类型 type CreatePoolFormInput = z.infer<typeof createPoolSchema>; // 定义 API 请求需要的类型(answers 转为数组) type CreatePoolApiRequest = Omit<CreatePoolFormInput, 'answers'> & { answers: string[] };
步骤2:给 useMutation 补充类型注解
通过给 mutationFn 的参数添加类型,让 TypeScript 正确识别 mutate 接收的参数类型:
const { mutate } = useMutation({ mutationFn: (data: CreatePoolApiRequest) => { return axios.post('/api/pool', data); }, onSuccess: () => { toast.success('Pool created'); }, });
也可以通过指定泛型参数的方式实现:
const { mutate } = useMutation<axios.AxiosResponse, unknown, CreatePoolApiRequest>({ mutationFn: (data) => { return axios.post('/api/pool', data); }, onSuccess: () => { toast.success('Pool created'); }, });
步骤3:确认 useForm 封装的正确性
你的自定义 useForm 已经正确基于 Zod Schema 推断类型,这部分无需修改,只需确保 createPoolSchema 的定义符合业务需求即可。
完整修正后的代码
import { z } from 'zod'; import { useForm } from './path-to-your-useForm'; // 替换为你的 useForm 文件路径 import { useMutation } from '@tanstack/react-query'; import axios from 'axios'; import { toast } from 'react-hot-toast'; // 定义 Zod 校验规则 const createPoolSchema = z.object({ question: z.string(), answers: z.string(), expiresAt: z.date(), isPublic: z.boolean(), }); type CreatePoolFormInput = z.infer<typeof createPoolSchema>; type CreatePoolApiRequest = Omit<CreatePoolFormInput, 'answers'> & { answers: string[] }; export const useCreatePoolForm = () => { const { submit, register, errors, watch } = useForm(createPoolSchema); const { mutate } = useMutation({ mutationFn: (data: CreatePoolApiRequest) => { return axios.post('/api/pool', data); }, onSuccess: () => { toast.success('Pool created'); }, }); const createPool = submit((pool) => { const answersToArray = pool.answers.split(',').map(answer => answer.trim()); mutate({ ...pool, answers: answersToArray, }); }); return { createPool, register, errors, watch, }; };
内容的提问来源于stack exchange,提问作者IvonaK
相关产品推荐
相关产品推荐

