阿波罗客户端 v3 "Cache data may be lost when replacing the field X of a Y object"
Apollo client v3 "Cache data may be lost when replacing the field X of a Y object"
我有两个简单的查询:
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
不适用于这种情况,因为两个菜单的标签可能相同
所以如果没有你的模式类型定义,你的问题很难回答。但是让我们假设它是这样的:
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
}
By default, the cache stores a separate value for every unique combination of argument values you provide when querying a particular field.
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
的结果合并到一个 Menus
缓存对象中,同时包含 menuA
和 menuB
属性。没有它,每次你 运行 一个查询时,你会吹走上一个查询的结果。
我有两个简单的查询:
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
不适用于这种情况,因为两个菜单的标签可能相同
所以如果没有你的模式类型定义,你的问题很难回答。但是让我们假设它是这样的:
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
}
By default, the cache stores a separate value for every unique combination of argument values you provide when querying a particular field.
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
的结果合并到一个 Menus
缓存对象中,同时包含 menuA
和 menuB
属性。没有它,每次你 运行 一个查询时,你会吹走上一个查询的结果。