使用ApolloClient归一化GraphQL查询响应缓存未更新求助
问题分析与解决方案
首先,你的代码存在语法错误,导致字段处理函数无法正确返回转换后的数据,这是缓存未更新的直接原因。其次,需要明确Apollo Client字段策略中read和merge函数的差异,根据你的归一化需求选择合适的处理方式。
1. 修复语法错误
你的map箭头函数缺少闭合括号,导致函数没有返回值。修改后的代码如下:
export const GRAPHQL_CLIENT_CONFIG = { link: from([errorLink, new HttpLink({uri: '/graphql'})]), cache: new InMemoryCache({ typePolicies: { Query: { fields: { nationsList:(existing, options)=>{ console.log("existing",existing) // 修复括号闭合问题,增加空数组兜底避免undefined return existing?.map(nation=> ({ label: nation?.acronyms, value: nation?.description })) || []; } } } } }) }
2. 选择合适的归一化方式
根据你的需求,有两种常见的归一化处理方式:
方式一:读取时转换(缓存保留原始数据)
如果希望缓存中存储查询返回的原始结构,仅在组件读取数据时转换为{label, value}格式,使用read函数:
cache: new InMemoryCache({ typePolicies: { Query: { fields: { nationsList: { read(existing) { // existing是缓存中的原始数据,读取时转换结构 return existing?.map(nation => ({ label: nation?.acronyms, value: nation?.description })) || []; } } } } } })
方式二:写入时转换(缓存存储归一化后的数据)
如果希望缓存直接存储转换后的{label, value}结构,使用merge函数(查询返回数据时直接转换并存入缓存):
cache: new InMemoryCache({ typePolicies: { Query: { fields: { nationsList: { merge(existing, incoming) { // incoming是查询返回的原始数据,转换后存入缓存 return incoming?.map(nation => ({ label: nation?.acronyms, value: nation?.description })) || []; } } } } } })
方式三:实体级归一化(推荐用于复杂场景)
如果你的nationsList中的每个国家有唯一标识(如id字段),建议采用Apollo Client的实体归一化,这样可以实现数据的自动同步更新。步骤如下:
第一步:修改查询,返回唯一标识字段
export const GET_NATIONS_LIST = gql(` query getNationsList{ nationsList{ id # 新增唯一标识字段 acronyms description } } `)
第二步:配置实体类型策略
cache: new InMemoryCache({ typePolicies: { // 定义Nation实体的唯一标识字段 Nation: { keyFields: ['id'], }, Query: { fields: { nationsList: { read(existing, { readField }) { // 将缓存中的实体ID数组转换为目标结构 return existing?.map(nationId => ({ label: readField('acronyms', nationId), value: readField('description', nationId) })) || []; } } } } } })
这种方式下,缓存会单独存储每个Nation实体,Query.nationsList仅存储实体ID数组。当其他操作修改某个Nation的数据时,nationsList的缓存会自动更新。
内容的提问来源于stack exchange,提问作者Alberto Manuguerra
相关产品推荐
相关产品推荐

