React Apollo Hooks:链式执行Mutations及加载状态处理问题
链式调用两个Mutation的正确姿势
我来帮你搞定这个问题~你遇到的核心问题有两个:一是原代码里的recordId是if块内的局部变量,外面根本访问不到;二是没有正确处理第一个mutation的Promise执行结果和错误情况。咱们一步步来调整:
首先,理清核心问题
你的原代码里,await createRecord()之后拿到的结果其实是Apollo mutation的返回对象,不是直接的ID;而且recordId定义在if块内部,后面调用saveValue的时候根本拿不到这个值,这肯定会失效。另外,你还需要处理加载状态和错误,避免用户重复提交或者看不到失败提示。
完整解决方案代码
import { useState } from 'react'; import { useMutation } from '@apollo/client'; // 假设你的两个query已经定义好了 import createRecordQuery from './queries/createRecord'; import saveValueQuery from './queries/saveValue'; const YourFormComponent = ({ recordId }) => { const [isSaving, setIsSaving] = useState(false); const [createRecord, { error: createError }] = useMutation(createRecordQuery); const [saveValue, { error: saveError }] = useMutation(saveValueQuery); const onSave = async (values) => { setIsSaving(true); let currentRecordId = recordId; // 先拿到已有记录ID try { // 如果没有现有ID,先执行创建记录的mutation if (!currentRecordId) { const createResult = await createRecord(); // 这里要根据你的GraphQL返回结构提取ID,比如你的mutation返回的是createRecord字段下的id currentRecordId = createResult.data.createRecord.id; } // 拿到ID后,执行保存值的mutation await saveValue({ variables: { recordId: currentRecordId, values } }); // 这里可以加成功后的逻辑,比如提示用户、重置表单或者跳转 alert("记录保存成功!"); } catch (err) { // 处理错误,比如区分是创建失败还是保存失败 if (createError) { console.error("创建记录失败:", createError); alert("创建记录失败,请稍后重试"); } else if (saveError) { console.error("保存值失败:", saveError); alert("保存值失败,请稍后重试"); } else { console.error("未知错误:", err); alert("保存失败,请稍后重试"); } // 向上抛出错误,让表单组件(比如Formik、React Hook Form)处理错误状态 throw err; } finally { // 不管成功还是失败,都结束加载状态 setIsSaving(false); } }; return ( // 你的表单JSX,按钮可以根据isSaving设置disabled或者显示loading <button onClick={() => onSave(formValues)} disabled={isSaving}> {isSaving ? "保存中..." : "保存"} </button> ); }; export default YourFormComponent;
关键细节说明
- 变量作用域修复:把
currentRecordId提升到if块外,确保后续调用saveValue时能拿到创建后的ID。 - Promise与错误处理:用
try/catch包裹整个流程,捕获两个mutation可能出现的错误,同时用finally确保加载状态一定会被重置。 - 加载状态控制:自己维护
isSaving状态,用来统一控制表单按钮的禁用状态和加载提示,比单独用两个mutation的loading状态更方便。 - 正确提取返回ID:要根据你实际的GraphQL mutation返回结构来提取ID,比如如果你的
createRecordQuery返回的是{ createRecord: { id, name } },那就要用createResult.data.createRecord.id来获取。
另外,如果你想单独区分“创建中”和“保存中”的状态,也可以用两个mutation自带的loading字段:
const [createRecord, { loading: isCreating }] = useMutation(createRecordQuery); const [saveValue, { loading: isSavingValue }] = useMutation(saveValueQuery);
然后在UI上根据isCreating显示“创建记录中...”,isSavingValue显示“保存值中...”,不过全局的isSaving状态仍然很有用,用来防止用户重复点击提交按钮。
内容的提问来源于stack exchange,提问作者Tdy
相关产品推荐
相关产品推荐

