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

Apollo 3.0如何通过typePolicies填充客户端Schema?

Apollo Client 3.x 本地状态typePolicies配置后查询返回异常

客户端Schema定义

const typeDefs = gql`
    extend type Query @client {
        getMessageSliceByIdMessaging(id_messaging: String!): [MESSAGE_SLICE]!
    }

    type MESSAGE_SLICE {
        _id: String!
        __typename: String!
        newest_date_creation: String!
        oldest_date_creation: String!
        list_id_message: [MESSAGE]!
    }
`

InMemoryCache的typePolicies配置

typePolicies: {
   Query: {
      fields: {
         getMessageSliceByIdMessaging : {
            merge(existing = [], incoming = [], {cache}) {
               // 执行自定义逻辑
               return some_shenanigans
            },
            read(existing = []) {
               return [...existing] // existing能正确返回merge生成的some_shenanigans
            },
         }
      }
   }
}

查询与数据写入代码

MESSAGE_SLICE片段

const MESSAGE_SLICE_FRAGMENT = gql`
    fragment MessageSliceFragment on MESSAGE_SLICE {
        _id
        newest_date_creation
        oldest_date_creation
        list_id_message {
            ...messageFragment
        }
    }
    ${MESSAGE_FRAGMENT}
`

获取MESSAGE_SLICE列表的查询

const GET_MESSAGE_SLICE_BY_ID_MESSAGING = gql`
    query getMessageSliceByIdMessaging (
        $id_messaging: String!
    ) {
        getMessageSliceByIdMessaging @client (
            id_messaging: $id_messaging
        ) {
            ...MessageSliceFragment
        }
    }
    ${MESSAGE_SLICE_FRAGMENT}
`

查询调用与数据写入

// 调用查询
const messageSliceListData = useQuery(GET_MESSAGE_SLICE_BY_ID_MESSAGING, {
   variables: {
      id_messaging: route.id_messaging,
   },
})

// 写入数据到缓存
await client.writeQuery({
   query: GET_MESSAGE_SLICE_BY_ID_MESSAGING,
   variables: {
      id_messaging,  
   }, 
   data: {getMessageSliceByIdMessaging: [...SOME_ARRAY_DATA_THAT_NEED_TO_BE_MERGE_IN_THE_TYPE_POLICIES]}
})

问题现象

messageSliceListData?.data始终返回[{}]或undefined,无任何报错。

已尝试的解决方法

  • 使用toReference将some_shenanigans作为引用返回;
  • 直接返回some_shenanigans原始数据。

正确实现方案

  1. 配置keyArgs区分缓存条目
    由于查询依赖id_messaging变量,必须在typePolicies中指定keyArgs,让Apollo根据变量值区分不同的缓存条目,否则所有查询会共用同一个缓存,导致数据异常:
typePolicies: {
  Query: {
    fields: {
      getMessageSliceByIdMessaging : {
        keyArgs: ["id_messaging"], // 关键:根据id_messaging区分缓存
        merge(existing = [], incoming = [], {cache}) {
          // 自定义合并逻辑,确保返回的数组每个元素都符合MESSAGE_SLICE结构
          return some_shenanigans;
        },
        read(existing = []) {
          return existing; // 无需额外复制,直接返回即可
        },
      }
    }
  }
}
  1. 确保数据结构完整性
    合并后返回的some_shenanigans数组中,每个MESSAGE_SLICE对象必须包含:
  • 正确的__typename: "MESSAGE_SLICE"字段;
  • Schema定义的所有必填字段(_id、newest_date_creation等);
  • list_id_message中的每个MESSAGE对象同样需要包含__typename和唯一标识字段(如_id),否则缓存无法解析,会返回空对象{}。
  1. 验证writeQuery的变量匹配
    调用writeQuery时,传入的variables必须与查询定义的变量完全一致,确保缓存能正确关联到对应条目中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:27:39