Apollo Client缓存覆盖问题求助:区分同名键的不同查询数据
解决Apollo缓存中同名查询字段覆盖问题
优先方案:查询字段别名
最直接的解决方式是在GraphQL查询中给getUserData添加别名,让两个查询返回的顶层字段名不同:
# QueryOne query QueryOne { getUserProfileData: getUserData { id name email } } # QueryTwo query QueryTwo { getUserSettingsData: getUserData { id theme notificationEnabled } }
这样Apollo缓存会分别存储getUserProfileData和getUserSettingsData,不会出现覆盖问题,无需修改缓存配置,成本最低。
方案二:自定义缓存ID生成逻辑
如果无法修改查询,可以通过dataIdFromObject函数为不同场景的getUserData生成唯一缓存ID。前提是返回的用户数据中有可区分的标识(比如额外的类型字段,或者结合查询变量):
import { InMemoryCache, defaultDataIdFromObject } from '@apollo/client'; const cache = new InMemoryCache({ dataIdFromObject: (object) => { // 假设用户数据的__typename是User,且包含userId和dataType字段(比如'profile'/'settings') if (object.__typename === 'User' && object.dataType) { return `User:${object.userId}:${object.dataType}`; } // 其他类型沿用默认逻辑 return defaultDataIdFromObject(object); } });
如果后端没有返回dataType,也可以考虑在查询时通过变量传递类型标识,然后在缓存写入时结合变量生成ID(需要配合typePolicies的merge逻辑)。
方案三:自定义字段读取策略
通过typePolicies为getUserData字段添加自定义读取逻辑,结合查询上下文区分不同查询的缓存数据:
import { InMemoryCache, gql } from '@apollo/client'; const cache = new InMemoryCache({ typePolicies: { Query: { fields: { getUserData: { read(existingData, { args, context }) { // 从查询上下文获取标识,区分是QueryOne还是QueryTwo const queryType = context.queryType; if (!queryType) return existingData; // 根据查询类型读取对应的缓存片段 return queryType === 'profile' ? cache.readFragment({ fragment: gql` fragment UserProfile on User { id name email } `, id: `User:${args.userId}` // 假设查询有userId参数 }) : cache.readFragment({ fragment: gql` fragment UserSettings on User { id theme notificationEnabled } `, id: `User:${args.userId}` }); } } } } } });
发起查询时传递上下文:
client.query({ query: QueryOne, variables: { userId: 123 }, context: { queryType: 'profile' } }); client.query({ query: QueryTwo, variables: { userId: 123 }, context: { queryType: 'settings' } });
方案四:临时规避(不推荐)
如果以上方案都无法实施,可以为特定查询设置fetchPolicy绕过缓存,但会失去缓存带来的性能优势:
client.query({ query: QueryTwo, fetchPolicy: 'network-only' // 每次都请求网络,不读取缓存 });
内容的提问来源于stack exchange,提问作者user615297
相关产品推荐
相关产品推荐

