react-hook-form+tRPC+Prisma:表单提交后无法保存mutation返回数据
问题分析与解决方案
核心问题原因
普通变量无法持久化:组件每次重新渲染时,
let savedTitle会被重新声明并初始化为undefined。mutation的回调是异步执行的,当回调触发时,组件可能已经完成重新渲染,此时回调里引用的savedTitle和外部的变量并非同一引用,赋值后无法在外部读取到更新后的值;同时你在mutate后立刻执行的console.log(savedTitle)是同步操作,此时异步回调还未触发,自然看不到更新结果。useState的错误用法:你之前尝试的
setSavedTitle(await datesQuery.refetch())存在两个问题:一是onSuccess回调不能直接使用await(除非声明为异步函数),二是refetch()返回的是整个查询结果列表,而非单个Title对象。代码笔误:逻辑判断里的
!possibleDate是拼写错误,应该是!possibleTitle,这会导致分支判断完全错误。
修正后的完整代码示例
import { useState, useEffect } from 'react'; import { SubmitHandler } from 'react-hook-form'; import { type Title } from "@prisma/client"; import { useQueryClient } from '@tanstack/react-query'; // 用于更新查询缓存 // 组件内部代码 const queryClient = useQueryClient(); const [savedTitle, setSavedTitle] = useState<Title | undefined>(); const titlesQuery = api.edit.getTitles.useQuery(); const titlesMutation = api.edit.newTitle.useMutation({ // 可选:mutation成功后自动刷新查询缓存,确保titlesQuery能获取最新数据 onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['edit', 'getTitles'] }); // 替换为你的实际queryKey }, }); const formSubmit: SubmitHandler<FormSchemaType> = (formData) => { const { title } = formData; const possibleTitle = titlesQuery.data?.find((t) => t.title === title); if (!possibleTitle) { titlesMutation.mutate(title, { onSuccess: (newTitle) => { // 直接用mutation返回的新Title对象更新state setSavedTitle(newTitle); }, onError: (err) => { console.error('创建标题失败:', err); }, }); } else { setSavedTitle(possibleTitle); } }; // 监听savedTitle的状态变化,查看更新后的值(替代直接在formSubmit里打印) useEffect(() => { if (savedTitle) { console.log('最终保存的Title对象:', savedTitle); } }, [savedTitle]);
关键说明
- useState的正确使用:通过
setSavedTitle直接传入mutation返回的newTitle(或已存在的possibleTitle),React会自动处理state的异步更新,并触发组件重新渲染。 - 异步结果的查看:由于state更新是异步的,不能在调用
setSavedTitle后立刻打印savedTitle,需要通过useEffect监听savedTitle的变化来查看最终值。 - 缓存更新:使用
queryClient.invalidateQueries可以让titlesQuery自动重新获取最新的标题列表,确保后续操作能拿到数据库的最新状态。
内容的提问来源于stack exchange,提问作者Daniel Guedes
相关产品推荐
相关产品推荐

