在 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 和新Productprice 字段中的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 接口实现缓存?

Apollo Client 3.0 中的 WebSocketClient 如何传递认证令牌?

带有命名空间查询的 Apollo Client 3.0 缓存