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

React项目使用GraphQL+Apollo编辑集合点击保存无响应问题

问题根因

点击保存无响应是代码存在多处语法和逻辑错误导致的,具体问题点:

  • React事件属性命名错误:所有事件绑定用了小写onclick,React只识别驼峰格式的onClick;且onSubmit事件仅表单元素支持,绑定在Button上完全不会触发;另外保存按钮额外绑定了关闭弹窗的事件,点击后会直接关弹窗,后续逻辑根本无法执行。
  • 组件Props接收方式错误:函数组件的Props是第一个入参,原代码写为(id, { isPublic = false }),会导致传入的id、name等参数全部无法正确读取。
  • 输入框未做状态绑定:Input的value和onChange被注释,属于非受控组件,用户输入的新名称完全无法被获取;提交时引用的name变量未定义,会直接抛出JS错误阻断执行。
  • GraphQL Mutation逻辑错误:更新接口未传入要修改的集合id,后端无法定位要更新的数据;缓存更新逻辑完全照搬新增Todo的示例代码,读取不存在的insert_todos字段,不仅无法更新缓存还会抛错。
  • 存在大量无效代码:定义了未使用的open/handleOpen/handleClose状态,调用了未引入定义的message方法,都会导致代码运行异常。
  • 编辑交互缺失:打开弹窗时未回填集合原有名称,用户看不到旧值,体验不符合预期。
修复代码

1. 修正EditCollection组件

import { useState } from "react";
import {
  Input,
  Modal,
  ModalBody,
  ModalFooter,
  ModalHeader,
  Button,
} from "reactstrap";
import { gql, useMutation } from "@apollo/client";
import { GET_PRODUCTS } from "./dashboard";

// 补全id入参,和后端接口字段对齐
const UPDATE_COLLECTION = gql`
  mutation updateCollection($id: ID!, $name: String!) {
    updateCollection(id: $id, updateCollection: { name: $name }) {
      id
      name
    }
  }
`;

// 正确解构Props参数
const EditCollection = ({ id, name, isPublic = false }) => {
  const [modal, setModal] = useState(false);
  const togglePopup = () => setModal(!modal);
  // 初始化输入值为原集合名称,打开弹窗直接回填
  const [collectionInput, setCollectionInput] = useState(name);
  const [updateCollection, { loading }] = useMutation(UPDATE_COLLECTION, {
    update: (cache, { data }) => {
      if (isPublic) return null;
      // 读取现有列表缓存
      const existingData = cache.readQuery({ query: GET_PRODUCTS });
      // 替换对应ID的集合数据,不要用新增逻辑
      const updatedList = existingData.collections.map(item => 
        item.id === id ? data.updateCollection : item
      );
      // 写回缓存
      cache.writeQuery({
        query: GET_PRODUCTS,
        data: { collections: updatedList },
      });
    },
    onCompleted: () => {
      togglePopup(); // 保存成功关闭弹窗
    }
  });

  const handleSave = () => {
    if (!collectionInput.trim()) return; // 简单判空
    updateCollection({
      variables: {
        id,
        name: collectionInput
      }
    });
  };

  return (
    <div>
      <Button onClick={togglePopup} style={{ backgroundColor: "transparent", border: "none" }}>
        <i className="fa fa-pencil-square-o mr-1" aria-hidden="true"></i>
      </Button>

      <Modal isOpen={modal} toggle={togglePopup} centered style={{ padding: "1rem" }}>
        <ModalHeader toggle={togglePopup} style={{ padding: "1rem" }}>
          <h3>编辑集合</h3>
        </ModalHeader>
        <ModalBody style={{ padding: "2rem" }}>
          <Input
            id="collectionName"
            name="name"
            placeholder="请输入新的集合名称"
            type="text"
            // 绑定受控属性
            value={collectionInput}
            onChange={(e) => setCollectionInput(e.target.value)}
          />
        </ModalBody>
        <ModalFooter style={{ paddingRight: "2rem" }}>
          <Button color="primary" onClick={handleSave} disabled={loading}>
            {loading ? "保存中..." : "保存"}
          </Button>
          <Button onClick={togglePopup}>取消</Button>
        </ModalFooter>
      </Modal>
    </div>
  );
};

export default EditCollection;

2. 修正组件调用方式

调用编辑组件时需要把集合原名称传入,用于弹窗回填:

const AllCollections = ({ id, name, img }) => {
  return (
    <tr>
      <th scope="row">
        <Media src={img} className="blur-up lazyloaded" />
      </th>
      <td>{id}</td>
      <td>{name}</td>
      <td>
        <EditCollection id={id} name={name} />
        <i className="fa fa-trash-o ml-1" aria-hidden="true"></i>
      </td>
    </tr>
  );
};
适配说明
  • 缓存更新部分的collections字段名,需要和你GET_PRODUCTS查询中返回的集合列表字段名保持一致,如果你的查询用了其他命名,替换为对应字段即可。
  • 如果后端更新接口的入参结构和示例Mutation有差异,按照实际接口文档调整UPDATE_COLLECTION的参数结构即可,核心是必须传入要修改的集合ID,否则后端无法定位目标数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 17:12:28