在 Apollo Client 3 中合并非规范化数据时出现“缓存数据可能丢失”警告
Posted
技术标签:
【中文标题】在 Apollo Client 3 中合并非规范化数据时出现“缓存数据可能丢失”警告【英文标题】:"Cache data may be lost" warning when merging non-normalized data in Apollo Client 3 【发布时间】:2020-12-14 11:29:54 【问题描述】:我正在使用 Apollo Client 将我的应用程序从 v2 升级到 v3,但我找不到以下问题的正确解决方案。
我有一个产品架构,在这个产品内部有一个价格。这个价格不是一个简单的数字,因为它包含免税价值、所有含税价值和增值税。
type Product
id: ID
price: Price
type Price
dutyFree: Float
allTaxesIncluded: Float
VAT: Float
在 Apollo Client 2 中,只要没有明确的 id 或 _id 属性,InMemoryCache 就会根据对象的路径创建一个备用假标识符来规范化数据。
在 Apollo Client 3 中,不再生成此备用假标识符。相反,您有两个选项来处理非规范化数据。第一个是使用新的 TypePolicy 选项,并明确指出您收到的数据不应该被规范化。在这种情况下,数据将链接到父标准化数据。
文档:
未规范化的对象改为嵌入缓存中的父对象中。您不能直接访问这些对象,但可以通过它们的父对象访问它们。
new InMemoryCache(
typePolicies:
Price
keyFields: false
)
很高兴,虽然我的问题已经解决了。好吧,错了……我可以在我的应用程序中创建产品并添加价格。但每当我更改现有价格时,我都会收到以下警告:
替换产品对象的价格字段时,缓存数据可能会丢失。
因为,当我更新后获取我的产品时,InMemoryCache 不知道如何合并字段价格,因为没有定义 id,这是非规范化数据的点。
我知道第二个选项可以为我的 Product.price 字段显式定义合并函数,但这个示例是现实的更简单版本。我通过多个类型为 Price 的对象有大量字段,并且为每个对象手动定义一个合并函数(甚至通过外部化函数中的通用逻辑)是我发现效率很低和错误的来源。
所以我的问题是:我对 keyFields: false
选项有什么误解,我可以做些什么来解决这个问题,而不必在我的应用程序中为 50 多个字段定义合并函数?
感谢您的帮助:)
【问题讨论】:
【参考方案1】:我不确定你是否误解了keyFields: false
。我的理解是,当Product
在缓存中更新时,InMemoryCache
必须处理嵌入在旧Product
和新Product
的price
字段中的Price
对象中的任何差异。如果没有 TypePolicy
来定义应该如何完成,缓存会记录一个警告。
从 Apollo Client 3.3 开始,merge
函数可以是 defined for types in addition to fields。这是他们文档中的一个示例:
const cache = new InMemoryCache(
typePolicies:
Book:
fields:
// No longer necessary!
// author:
// merge: true,
// ,
,
,
Author:
merge: true,
,
,
);
由于您不想逐个字段定义合并函数,您可以尝试为 Price
类型定义合并函数。
【讨论】:
以上是关于在 Apollo Client 3 中合并非规范化数据时出现“缓存数据可能丢失”警告的主要内容,如果未能解决你的问题,请参考以下文章
如何为 Vue Apollo 导入 Apollo Client 3?
带有 Apollo-Client 3 警告的 WebStorm 未知指令 @client
我正在将 vue 3 与 apollo/client 一起使用,但出现错误
Apollo Client 3:如何在客户端为 graphql 接口实现缓存?