如何在GraphQL/Apollo/React中完成多轮Mutation后重新获取数据
问题场景与现有尝试
业务需求
- 需调用两个
useMutation操作数据库:完成创建/更新操作 - 第二个Mutation必须在第一个执行成功后触发,且需要遍历数组循环调用第二个Mutation
- 所有Mutation执行完成后,必须重新调用另一个API以更新缓存(因为这两个Mutation会影响缓存数据)
现有尝试及问题
方法1:使用Promise.all
const [creatEnrollment] = useMutation(mut1) const [updateEnrollment] = useMutation(mut2) const [toFetch, {loading, error, data}] = useLazyQuery(UsersDocument) await Promise.all([creatEnrollment(), updateEnrollment()]) const result = () => toFetch({ variables: {name: 'i'} })
- 问题:无法保证第二个Mutation在第一个之后执行,也无法实现循环调用第二个Mutation
方法2:使用React Query的onSuccess回调
const mutate1 = useMutation((data) => axios.post('/something', { data })) const mutate2 = useMutation(somethingResult => axios.put('/somethingElse', { somethingResult })) <button onClick={() => { mutate1.mutate('data', { onSuccess: mutate2.mutate }) }} />
- 问题:不知道如何循环调用
mutate2,也不清楚如何在所有mutate2执行完成后触发数据重获取
解决方案
可以结合onSuccess回调和Promise.all实现需求,具体步骤如下:
1. 定义Mutation与缓存更新查询
import { useMutation, useLazyQuery } from '@tanstack/react-query'; import axios from 'axios'; // 第一个创建操作的Mutation const { mutate: createEnrollment } = useMutation( (createData) => axios.post('/api/enrollments', createData), ); // 第二个更新操作的Mutation(返回Promise方便后续批量处理) const { mutate: updateEnrollment } = useMutation( (updateData) => axios.put('/api/enrollments/update', updateData), ); // 用于更新缓存的Lazy Query const [fetchUsers, { isLoading: isRefetching }] = useLazyQuery(UsersDocument);
2. 实现依赖与循环调用逻辑
先等待第一个Mutation执行成功,再遍历数组批量执行第二个Mutation,最后触发缓存重获取:
const handleBatchOperations = async (createData, updateItems) => { // 等待第一个创建Mutation执行完成 await new Promise((resolve, reject) => { createEnrollment(createData, { onSuccess: resolve, onError: reject, }); }); // 遍历数组,把每个更新操作包装成Promise const updatePromises = updateItems.map(item => new Promise((resolve, reject) => { updateEnrollment(item, { onSuccess: resolve, onError: reject, }); }) ); // 等待所有更新Mutation执行完成 await Promise.all(updatePromises); // 所有操作完成后,触发缓存重获取 await fetchUsers({ variables: { name: 'i' } }); };
3. 组件中触发执行
在按钮点击或其他交互时调用处理函数:
<button onClick={() => handleBatchOperations(yourCreateData, yourUpdateArray)} disabled={isRefetching} > 执行批量操作 </button>
关键说明
- 用
Promise包装mutate调用,通过await确保第一个Mutation执行完成后再处理后续逻辑 - 遍历待更新数组,将每个
updateEnrollment调用转为Promise,用Promise.all等待全部更新完成 - 所有操作结束后调用缓存查询,保证前端数据与后端同步
内容的提问来源于stack exchange,提问作者Hongli Bu
相关产品推荐
相关产品推荐

