Apollo GQL useMutation执行成功但返回对象缺失data字段问题
问题产生原因
这个问题是useMutation的执行机制和使用方式错误导致的,核心点有三个:
useMutation和组件挂载就自动执行的useQuery不同,它不会主动发请求,返回的状态对象(解构得到的data/loading/error)初始状态下不会携带data字段,只有手动触发mutation、请求完成并触发组件重渲染后,data才会被填充到状态对象里。- 你现在把
mutateFunction直接写在组件函数顶层同步执行,属于错误用法:组件每一次渲染都会触发一次新的mutation请求,你打印状态对象的时机永远早于请求完成的时机,自然拿不到data,还会造成重复请求的问题。 - 调用
mutateFunction是异步操作,你如果在调用mutateFunction之后立刻同步打印data,此时请求还在pending阶段,组件还没触发重渲染,拿到的必然是undefined。
修复方法
根据你的使用场景选一种即可:
方法1:直接通过mutate返回的Promise获取结果
mutateFunction本身返回Promise,请求完成后会直接resolve响应结果,不需要等待组件重渲染,适合在逻辑代码里拿返回值做后续处理:
// 把mutate调用放到事件回调中(比如表单提交、按钮点击事件),不要放在组件顶层 const handleSubmit = async () => { try { const result = await mutateFunction({ variables: { options: { title: bookmark.title, url: bookmark.url, }, }, }); // 此处可直接拿到返回数据 const createdBookmark = result.data.createBookmark.bookmark; console.log('创建成功的书签:', createdBookmark); } catch (requestError) { console.error('创建书签失败:', requestError); } };
方法2:从useMutation返回的状态对象读取渲染用数据
如果是在组件JSX中渲染返回结果,直接使用解构得到的data即可,注意做好加载状态和值存在性判断:
const [mutateFunction, { data, error, loading }] = useMutation(CREATE_BOOKMARK); return ( <div> <button onClick={() => mutateFunction({ variables: { options: { title: bookmark.title, url: bookmark.url, } } })} disabled={loading} > {loading ? '书签创建中...' : '新建书签'} </button> {error && <p className="error-tip">创建失败:{error.message}</p>} {data?.createBookmark?.bookmark && ( <div className="result"> <p>创建成功!书签名:{data.createBookmark.bookmark.title}</p> <p>书签地址:{data.createBookmark.bookmark.url}</p> </div> )} </div> );
这种写法下,mutation请求成功后Apollo Client会自动触发组件重渲染,此时状态对象里的data就会被正确赋值,之前你打印对象看不到data只是因为打印时机在请求完成之前。
内容的提问来源于stack exchange,提问作者Jonas Hendel
相关产品推荐
相关产品推荐

