带有命名空间查询的 Apollo Client 3.0 缓存
Posted
技术标签:
【中文标题】带有命名空间查询的 Apollo Client 3.0 缓存【英文标题】:Apollo Client 3.0 Cache with Namespaced Queries 【发布时间】:2020-12-24 00:23:26 【问题描述】:我有一些关于如何将 apollo 客户端缓存与我们组织查询的特定方式相匹配的问题。
因此,我们组织查询的方式是将同一资源上的查询分组到单个命名空间下。例如。我们有两个资源,users
和 accounts
,我们的查询看起来像这样。
type Query
user: UserQueries
account: AccountQueries
type UserQueries
all: [User!]!
byId(id: ID!): User
type AccountQueries
all: [Account!]!
byId(id: ID!): Account
type User ...
type Account ...
由于Queries
类型都没有提供ID 字段,默认情况下UserQueries
下的第二个查询的响应将替换缓存中第一个查询的数据,即首先我进行all
查询,然后我' 将取回一些存储在缓存中 user
字段下的数据。然后如果我进行byId
查询,user
下缓存中的数据将被新数据替换。
关于这个过程的一些问题:
-
我注意到,即使
all
数据被 byId
数据替换后,之前获取的用户(规范化的用户)仍然在缓存中可用,当我认为它们将被垃圾收集时,因为引用是丢失。垃圾收集器是否不会立即对它们进行垃圾收集,而是以一定的节奏运行?还是我完全误解了 gc 的工作原理?
除了为查询 typesuser
生成唯一 ID 之外,还有其他方法可以保留两个响应吗?
这样命名空间查询是个好主意吗?
谢谢各位!
【问题讨论】:
你知道多少好的命名空间 API? 【参考方案1】:正如您所经历的,结果将被不同的查询覆盖,因为缓存不知道从技术上讲查询总是返回相同的对象。
有两种解决方案:
您已经确定了第一个:给这些对象一个静态 ID 字段。这很丑陋。第二个是为这些查询字段编写merge
函数,如docs 中所述。我不认为命名空间通常是一个坏主意,但正如您所看到的,您必须为架构中的基本 any 实体类型编写此合并函数。因此,我建议谨慎使用命名空间。
垃圾收集器在 Apollo 3 中也得到了一些更新。它现在可以自定义并随时运行。您可以阅读有关 GC 的更多信息here。不再引用的对象可能会在缓存中保留一段时间。文档似乎没有指定 GC 的运行时间。可以通过调用client.gc()
手动运行。
【讨论】:
感谢@Herku!我们最终删除了命名空间,让我们的生活更轻松。【参考方案2】:实际上,在 Apollo 3 中使用命名空间查询的正确方法是将 keyFields
设置为空数组。
当你这样做时,你向 Apollo 表明没有用于合并的 id,因此所有内容都应该合并到同一个缓存键中。
您不必为此编写合并函数。
在InMemoryCache
配置中通过typePolicies
选项配置
const apolloClient = new ApolloClient(
cache: new InMemoryCache(
typePolicies:
UserQueries:
keyFields: [],
,
AccountQueries:
keyFields: [],
,
,
),
);
【讨论】:
以上是关于带有命名空间查询的 Apollo Client 3.0 缓存的主要内容,如果未能解决你的问题,请参考以下文章
使用 Apollo Client GraphQL 查询和修改表单
带有 Apollo-Client 3 警告的 WebStorm 未知指令 @client
我可以覆盖组件中单个查询的 Apollo Client 标头吗?