Angular Apollo缓存报错:如何为ManagedFilter.values定义自定义合并函数?
我在Angular Apollo中预先配置了Apollo缓存的字段合并规则,代码如下:
function mergeFields(existing: any, incoming: any) { return {...existing, ...incoming}; } function relaceFields(existing: any, incoming: any) { return incoming; } apolloCache = new InMemoryCache({ possibleTypes: possibleTypesResult.possibleTypes, typePolicies: { Query: { fields: { eligibleShippingMethods: { merge: relaceFields, }, }, }, Product: { fields: { customFields: { merge: mergeFields, }, }, }, Collection: { fields: { customFields: { merge: mergeFields, }, }, }, Order: { fields: { lines: { merge: relaceFields, }, shippingLines: { merge: relaceFields, }, discounts: { merge: relaceFields, }, shippingAddress: { merge: relaceFields, }, billingAddress: { merge: relaceFields, }, }, }, Customer: { fields: { addresses: { merge: relaceFields, }, customFields: { merge: mergeFields, }, }, }, }, });
现在收到如下错误提示:
替换ManagedFilter对象的values字段时可能会丢失缓存数据。
这可能会导致额外的(通常可避免的)网络请求来获取原本已缓存的数据。
要解决此问题(并非Apollo Client的bug),请为ManagedFilter.values字段定义自定义合并函数,以便InMemoryCache可以安全地合并这些对象:
existing: [ {
"__ref": "ManagedFilterValue:276" }, {
"__ref": "ManagedFilterValue:260" }, {
"__ref": "ManagedFilterValue:247" }, {
"__ref": "ManagedFilterValue:254" }, {
"__ref": "ManagedFilterValue:253" }, {
"__ref": "ManagedFilterValue:230" } ] incoming: [ {
"__ref": "ManagedFilterValue:260" } ]
我调用的查询为:
Query.search( input: SearchInput! ): SearchResponse!
返回结构:
type SearchResponse { items: [SearchResult!]! totalItems: Int! facetValues: [FacetValueResult!]! collections: [CollectionResult!]! topFilters: [ManagedFilter!]! leftFilters: [ManagedFilter!]! }
其中topFilters和leftFilters是ManagedFilter类型,结构如下:
type ManagedFilter { id: ID! languageCode: LanguageCode! name: String! code: String! values: [ManagedFilterValue!]! }
ManagedFilterValue结构:
type ManagedFilterValue { id: ID! languageCode: LanguageCode! filterId: ID! name: String! code: String! count: Int }
请问如何在apolloCache的typePolicies中添加ManagedFilter或ManagedFilterValue的配置,以消除Apollo Client的该错误提示?
根据错误提示,只需为ManagedFilter类型的values字段指定明确的合并策略即可,可根据业务需求选择以下两种方式:
方式1:直接替换(复用现有逻辑)
如果业务上每次查询返回的values是完整的最新集合,不需要保留旧数据,直接复用你已有的relaceFields函数:
在typePolicies中添加ManagedFilter的配置:
apolloCache = new InMemoryCache({ possibleTypes: possibleTypesResult.possibleTypes, typePolicies: { // 保留原有所有配置... ManagedFilter: { fields: { values: { merge: relaceFields, }, }, }, }, });
方式2:合并数组(保留并更新缓存项)
如果需要保留缓存中已有的ManagedFilterValue,同时根据__ref匹配更新新数据(比如实时更新count值),可以编写数组合并函数:
先新增合并函数:
function mergeArrayById(existing: any[] = [], incoming: any[] = []) { const merged = [...existing]; incoming.forEach(item => { const matchIndex = merged.findIndex(existingItem => existingItem.__ref === item.__ref); if (matchIndex !== -1) { merged[matchIndex] = item; } else { merged.push(item); } }); return merged; }
再配置到typePolicies中:
apolloCache = new InMemoryCache({ possibleTypes: possibleTypesResult.possibleTypes, typePolicies: { // 保留原有所有配置... ManagedFilter: { fields: { values: { merge: mergeArrayById, }, }, }, }, });
两种方式的选择依据:如果筛选操作后返回的values是全新的筛选结果集合,用方式1;如果需要累积缓存项或更新已有项的属性值,用方式2。
内容的提问来源于stack exchange,提问作者PokerJoker

