我正在使用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
}
}
})
很高兴,尽管我的问题解决了,但我还是很高兴。好吧,错了。。。我可以在我的应用中创建产品并添加价格。但是,只要更改现有价格,就会收到以下警告:
替换Product对象的price字段时,缓存数据可能会丢失。
因为,当我在更新后获得我的产品时,InMemoryCache不知道如何合并“价格”字段,因为没有定义id,这是非规范化数据的关键所在。
我知道有第二个选项可以为我的Product.price字段显式定义合并函数,但是此示例是实际的简单版本。我有大量通过多个对象键入多个对象的字段,这些对象的类型为Price,而为每个对象手动定义一个合并函数(即使是通过外部化函数中的通用逻辑)也是我发现效率低下和产生错误的原因。
所以我的问题是:我对keyFields: false
选项有什么误解,我该怎么做才能解决此问题,而不必诉诸于在我的应用程序中为50多个字段定义合并功能?
感谢您的帮助:)
答案 0 :(得分:0)
我不确定您是否误解了 keyFields: false
。我的理解是,当 Product
在缓存中更新时,InMemoryCache
必须处理嵌入在旧 {{1} 的 Price
字段中的 price
对象中的任何差异} 和新的 Product
。如果没有 Product
来定义应该如何完成,缓存会记录警告。
从 Apollo Client 3.3 开始,TypePolicy
函数可以是 defined for types in addition to fields。这是他们文档中的一个示例:
merge
由于您不想逐个字段地定义合并函数,您可以尝试为 const cache = new InMemoryCache({
typePolicies: {
Book: {
fields: {
// No longer necessary!
// author: {
// merge: true,
// },
},
},
Author: {
merge: true,
},
},
});
类型定义合并函数。