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
相关产品推荐
相关产品推荐

