在 Apollo 客户端 3 中合并非规范化数据时出现"缓存数据可能会丢失"警告



我正在使用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对象的价格字段时,缓存数据可能会丢失。

因为,当我在更新后获得产品时,InMemoryCache不知道如何合并字段Price,因为没有定义id,这是非规范化数据的点。

我知道还有第二个选项可以显式地为我的Product.price字段定义一个合并函数,但这个例子是一个更简单的现实版本。我在多个类型为Price的对象中有大量字段,并且手动为每个对象定义一个合并函数(即使是通过在函数中外部化公共逻辑(,我发现这是非常低效的,也是错误的来源。

因此,我的问题是:我对keyFields: false选项有什么误解?在不必为应用程序中的50多个字段定义合并函数的情况下,我该如何解决这个问题?

感谢您的帮助:(

我不确定你是否误解了keyFields: false。我的理解是,当Product在缓存中更新时,InMemoryCache必须处理嵌入旧Product和新Productprice字段中的Price对象中的任何差异。如果没有TypePolicy来定义应该如何执行,那么缓存会记录一条警告。

从Apollo Client 3.3开始,除了字段之外,还可以为类型定义merge函数。下面是他们文档中的一个例子:

const cache = new InMemoryCache({
typePolicies: {
Book: {
fields: {
// No longer necessary!
// author: {
//   merge: true,
// },
},
},
Author: {
merge: true,
},
},
});

由于您不想逐个字段定义合并函数,因此可以尝试为Price类型定义合并函数。

最新更新