Apollo 客户端 v3“替换 Y 对象的字段 X 时可能会丢失缓存数据”
Posted
技术标签:
【中文标题】Apollo 客户端 v3“替换 Y 对象的字段 X 时可能会丢失缓存数据”【英文标题】:Apollo client v3 "Cache data may be lost when replacing the field X of a Y object" 【发布时间】:2021-05-25 21:54:20 【问题描述】:我有两个简单的查询:
query GerMenuA
menus
menuA
items
label
query GerMenuB
menus
menuB
items
label
但在控制台中我看到一个警告:
Cache data may be lost when replacing the menus field of a Query object.
existing: "__typename":"Menu","menuA":[...]
incoming: "__typename":"Menu","menuB":[...]
有没有办法不合并它们并删除警告?因为如果在typePolicies
中指定@
Menu: merge: true
or
Menu: merge: false
这不是我想要的,因为这些是不同的数据,这两个队列不需要以任何方式合并。另外,我没有id
字段,keyFields
不适用于这种情况,因为两个菜单的标签可能相同
【问题讨论】:
【参考方案1】:因此,如果没有您的架构类型定义,您的问题很难回答。但是让我们假设它是这样的:
type Query
menus: Menus
type Menus
menuA: Menu
menuB: Menu
警告本质上是说没有任何keyArgs
Apollo Cache 无法规范化menus
查询。从他们的角度记住 - 你有一个 single menus
root 查询。 (即GerMenuA
和GerMenuB
是客户端查询而不是root 查询)。
(旁注 - 因为您没有 id
字段,请参阅 disabling normalization。)
选项 1:分离您的查询
type Query
menuA: Menu
menuB: Menu
Apollo 缓存现在将 menuA
和 menuB
存储为单独的查询。如果您想安全起见,可以设置类型策略:
const createCache = () => new InMemoryCache(
typePolicies:
Menu:
keyFields: false
,
Query:
fields:
menuA:
keyArgs: false
,
menuB:
keyArgs: false
,
);
keyFields: false
告诉 AC 将 Menu
存储在它的父查询下。 keyArgs: false
表示 menuA
和 menuB
都是单例查询。缓存策略将默认为merge: false
,以便现有数据将被传入的数据替换。
选项 2:定义查询参数
在此选项中,您将 name
参数添加到您的 menus
查询中:
type Query
menus(name: String): Menu
默认情况下,缓存会为您在查询特定字段时提供的每个唯一参数值组合存储一个单独的值。
Apollo 缓存现在将 menus:name:menuA
和 menus:name:menuB
存储为单独的缓存对象。同样,如果您想安全起见,可以设置类型策略:
const createCache = () => new InMemoryCache(
typePolicies:
Menu:
keyFields: false
,
);
同样,缓存策略将默认为merge: false
,以便现有数据将被传入的数据替换。
选项 3:定义合并策略
我们已经讨论了为什么现有架构会令 Apollo Cache 感到困惑。但如果你真的准备好了,剩下要做的就是定义一个合并策略:
const createCache = () => new InMemoryCache(
typePolicies:
Menu:
keyFields: false
,
Menus:
keyFields: false,
merge: true
,
Query:
fields:
menus:
keyArgs: false,
merge: true
,
);
merge: true
告诉 Apollo Cache 将 GerMenuA
和 GerMenuB
的结果合并到具有 menuA
和 menuB
属性的单个 Menus
缓存对象中。每次运行查询时如果没有它,您会破坏前一个查询的结果。
【讨论】:
以上是关于Apollo 客户端 v3“替换 Y 对象的字段 X 时可能会丢失缓存数据”的主要内容,如果未能解决你的问题,请参考以下文章
更新 apollo 缓存而不调用 graphql 服务器(apollo v3.3)
如何在 useSubscription 挂钩中更新订阅变量 - Apollo v3
Apollo Client v3 在给定时间段后删除缓存条目
使用 apollo-server-express 迁移到 3.5.0