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

如何向嵌套数组的cards数组添加对象?遇对象不可扩展错误

解决Apollo Cache中“对象不可扩展”错误:向嵌套数组添加元素

问题场景

从GraphQL获取嵌套结构数据后,尝试向id为1的list项的cards数组添加新对象时,触发“对象不可扩展”错误。

数据示例

{
  "data": {
    "board": {
      "id": "1",
      "title": "Grocieries",
      "color": "teal",
      "lists": [
        {
          "id": "1",
          "title": "To-Do",
          "cards": [
            { "id": "1", "title": "Write novel" },
            { "id": "2", "title": "Buy food" },
            { "id": "3", "title": "Paint a picture" }
          ]
        },
        {
          "id": "2",
          "title": "In progress",
          "cards": [
            { "id": "4", "title": "Buy groceries" },
            { "id": "5", "title": "Pay the bills" }
          ]
        },
        {
          "id": "3",
          "title": "Done",
          "cards": [
            { "id": "8", "title": "Get the car fixed" },
            { "id": "9", "title": "Write novel" }
          ]
        }
      ]
    }
  }
}

报错代码

<script>
import CardAdd from '../graphql/mutations/CardAdd';
import BoardQuery from '../graphql/queries/BoardWithListsAndCards';
export default {
    methods: {
        cardAdd(){
            this.$apollo.mutate({
                mutation: CardAdd,
                variables: {
                    title: "Mutation added",
                    order: 1,
                    listId: 1,
                    ownerId: 1
                },
                update(store, { data: { cardAdd } }){
                    let data = store.readQuery({
                        query: BoardQuery,
                        variables: { id: 1 }
                    });
                    // 直接修改冻结对象触发错误
                    data.board.lists.find(list => list.id == 1).cards.push(cardAdd);
                }
            });
        }
    }
}
</script>

问题原因

Apollo Client返回的查询结果是不可变(冻结)对象,目的是防止意外修改缓存数据导致状态不一致。直接修改这些对象会触发“对象不可扩展”的错误。

解决方案

创建数据的深拷贝,修改拷贝后的对象,再通过store.writeQuery将更新后的数据写回缓存。

修改后的代码

<script>
import CardAdd from '../graphql/mutations/CardAdd';
import BoardQuery from '../graphql/queries/BoardWithListsAndCards';
export default {
    methods: {
        cardAdd(){
            this.$apollo.mutate({
                mutation: CardAdd,
                variables: {
                    title: "Mutation added",
                    order: 1,
                    listId: 1,
                    ownerId: 1
                },
                update(store, { data: { cardAdd } }){
                    // 1. 读取原始缓存数据
                    const originalData = store.readQuery({
                        query: BoardQuery,
                        variables: { id: 1 }
                    });

                    // 2. 深拷贝数据(避免直接修改冻结对象)
                    const updatedData = JSON.parse(JSON.stringify(originalData));

                    // 3. 找到目标list并添加新card(注意id类型匹配,原始数据为字符串)
                    const targetList = updatedData.board.lists.find(list => list.id === "1");
                    if (targetList) {
                        targetList.cards.push(cardAdd);
                    }

                    // 4. 将修改后的数据写回缓存
                    store.writeQuery({
                        query: BoardQuery,
                        variables: { id: 1 },
                        data: updatedData
                    });
                }
            });
        }
    }
}
</script>

额外说明

  • JSON.parse(JSON.stringify())是通用的深拷贝方式,如果数据包含函数、Symbol等特殊类型,建议使用lodash.cloneDeep这类专业工具。
  • 必须调用writeQuery将修改后的数据写回缓存,否则界面不会同步更新。
  • 使用===严格相等判断id,避免类型不匹配导致找不到目标list。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 14:50:38