调用useMutation内部请求成功却无法获取返回数据的问题
tRPC useMutation 无法立即获取返回数据的解决方案
问题核心原因
你遇到的问题本质是**mutate是异步操作**:调用mutate后不会同步返回请求结果,你紧接着访问dataMutation.data时,请求还在处理中,因此值为undefined;而onSuccess是请求成功后触发的回调,自然能拿到正确数据。
解决方案一:在onSuccess回调中处理结果
把依赖返回数据的逻辑(比如更新cardSets、page)移到onSuccess里,同时注意React状态更新的闭包问题,用函数式更新获取最新状态:
// fetch data const dataMutation = api.post.queryByFilter.useMutation({ onSuccess(data) { console.log("onSuccess: ", data); // 在这里处理返回的数据 const currentDate = new Date(); currentDate.setMonth(currentDate.getMonth() - monthsBack); const getMonth = (currentDate.getMonth() + 1).toString(); const getYear = currentDate.getFullYear().toString(); // 函数式更新避免闭包问题,获取最新状态 setCardSets(prev => [ ...prev, { data, month: getMonth, year: getYear } ]); setPage(prev => prev + 1); }, }); const fetchData = () => { // 用函数式更新monthsBack,确保状态更新逻辑正确 setMonthsBack(prev => prev + 1); const currentDate = new Date(); // 因setMonthsBack是异步的,直接用monthsBack+1计算目标日期 currentDate.setMonth(currentDate.getMonth() - (monthsBack + 1)); const getMonth = (currentDate.getMonth() + 1).toString(); const getYear = currentDate.getFullYear().toString(); dataMutation.mutate({ company: "google", month: getMonth, // 已经是字符串,无需重复toString() year: getYear, }); };
解决方案二:使用mutateAsync配合async/await
tRPC的useMutation提供了mutateAsync方法,它返回Promise,可通过await等待请求完成,同步获取返回数据:
// fetch data const dataMutation = api.post.queryByFilter.useMutation(); const fetchData = async () => { setMonthsBack(prev => prev + 1); const currentDate = new Date(); currentDate.setMonth(currentDate.getMonth() - (monthsBack + 1)); const getMonth = (currentDate.getMonth() + 1).toString(); const getYear = currentDate.getFullYear().toString(); try { // await等待请求完成,直接拿到返回数据 const data = await dataMutation.mutateAsync({ company: "google", month: getMonth, year: getYear, }); console.log("Fetch Data: ", data); // 处理数据 setCardSets(prev => [ ...prev, { data, month: getMonth, year: getYear } ]); setPage(prev => prev + 1); } catch (error) { // 处理请求失败场景 console.error("请求失败:", error); } };
额外注意事项
- 日期计算bug:
setMonthsBack(monthsBack + 1)是异步更新,后续直接用monthsBack会拿到旧值,导致日期计算错误,建议用monthsBack + 1直接计算或监听monthsBack变化处理。 - 冗余代码:
getMonth已经是toString()后的字符串,无需再调用getMonth.toString(),可直接删除。
内容的提问来源于stack exchange,提问作者Juan
相关产品推荐
相关产品推荐

