You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Apollo的useMutation实现带动态ID的表单数据更新

问题描述

我有一个GraphQL查询,用于获取表单展示所需的全部输入项,需要在输入框触发onChange事件时,通过同一个mutation来修改数据库。
已经完成查询逻辑并成功渲染所有输入框,现在遇到两个问题:

  1. 输入数据时,如何重新发送携带新值的mutation?
  2. 需要传递特定的id,让后端识别出是修改现有文章而非创建新文章。

现有代码文件

form.service.tsx

export const FORM = gql`
  mutation form($article: ArticleInput!) {
    form(annonce: $annonce) {
      article{
        id
      }
      formContent
    }
  }
`;

export const FormData = ({ children }) => {
  const [form, { data, loading, error }] = useMutation(
    form,
    {
      variables: {
        annonce: {
          idtype: 2,
          id: 0, // I need this to be dynamic
        },
      },
    },
  );

  useEffect(() => {
    form().then((res) => {
      if (res.data) {
        res.data.form.formContent = JSON.parse(
          res.data.form.formContent,
        );
      }
    });
  }, [form]);

  return children(data, loading, error);
};

form.tsx

<FormData>
      {(data, loading) => {
        if (loading) return <>loading...</>;

        return (
          <>
            <Section3 dataToDisplay={data.groups} />

section3.tsx

const Section3 = ({ data }) => {
  const [typeDeBienSelected, setTypeDeBienSelected] = useState<Group>(
    data.find((item) => item.selected) ?? data[0],
  );

  return (
    <div className="hk-flex hk-flex-col hk-gap-8">
      <MyInputComponent
        list={typeDeBien ?? []}
        value={typeDeBienSelected}
        setValue={(e) => setTypeDeBienSelected(e)}
      />
  );
};

export default Section3;

解决方案

1. 传递动态文章ID

通过给FormData组件传入articleId props,替换硬编码的id:0,让后端识别要修改的现有文章。

2. 输入变化时触发mutation

将mutation的触发逻辑封装成可复用的函数,传递给子组件,在输入框onChange时调用该函数,携带最新的表单值发送请求。


修改后的代码

form.service.tsx

export const FORM = gql`
  mutation form($article: ArticleInput!) {
    form(article: $article) { # 修正变量名与定义一致
      article{
        id
      }
      formContent
    }
  }
`;

export const FormData = ({ articleId, children }) => {
  const [formMutation, { loading, error }] = useMutation(FORM);
  const [formState, setFormState] = useState(null);

  // 初始化加载表单数据
  useEffect(() => {
    const fetchInitialForm = async () => {
      const res = await formMutation({
        variables: {
          article: {
            idtype: 2,
            id: articleId, // 使用传入的动态ID
          },
        },
      });
      if (res.data) {
        const parsedContent = JSON.parse(res.data.form.formContent);
        setFormState(parsedContent);
      }
    };
    fetchInitialForm();
  }, [formMutation, articleId]);

  // 封装表单更新函数,供子组件调用
  const updateForm = async (updatedFields) => {
    const newFormState = { ...formState, ...updatedFields };
    // 发送携带最新值的mutation
    const res = await formMutation({
      variables: {
        article: {
          idtype: 2,
          id: articleId,
          ...newFormState,
        },
      },
    });
    // 更新本地状态保持与后端同步
    if (res.data) {
      const parsedContent = JSON.parse(res.data.form.formContent);
      setFormState(parsedContent);
    }
  };

  return children({ formData: formState, loading, error, updateForm });
};

form.tsx

<FormData articleId={yourActualArticleId}> {/* 替换为实际的文章ID,比如从路由/父组件传入 */}
  {({ formData, loading, updateForm }) => {
    if (loading) return <>loading...</>;

    return (
      <>
        <Section3 dataToDisplay={formData.groups} updateForm={updateForm} />
      </>
    );
  }}
</FormData>

section3.tsx

const Section3 = ({ dataToDisplay, updateForm }) => {
  const [typeDeBienSelected, setTypeDeBienSelected] = useState<Group>(
    dataToDisplay.find((item) => item.selected) ?? dataToDisplay[0],
  );

  const handleSelectionChange = (selectedItem) => {
    setTypeDeBienSelected(selectedItem);
    // 触发mutation更新,字段名根据实际业务调整
    updateForm({ typeDeBien: selectedItem });
  };

  return (
    <div className="hk-flex hk-flex-col hk-gap-8">
      <MyInputComponent
        list={dataToDisplay ?? []}
        value={typeDeBienSelected}
        setValue={handleSelectionChange}
      />
    </div>
  );
};

export default Section3;

关键说明

  • 动态ID:通过articleId props传入具体的文章ID,mutation调用时携带该ID,后端即可识别是修改操作而非创建。
  • 触发时机:在输入框值变化时,先更新本地状态保证UI响应,再调用updateForm发送mutation,携带最新的表单字段值,同时根据后端返回结果更新本地状态,保持数据一致性。
  • 变量名修正:原mutation定义的变量是$article,调用时对应的参数名需统一为article,避免GraphQL变量不匹配错误。

内容的提问来源于stack exchange,提问作者Johan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:05:43