GraphQL/Apollo 客户端:如果查询是先前查询的子集,则从缓存中获取数据
Posted
技术标签:
【中文标题】GraphQL/Apollo 客户端:如果查询是先前查询的子集,则从缓存中获取数据【英文标题】:GraphQL/Apollo Client: get data from cache if a query is a subset of a previous query 【发布时间】:2020-10-24 16:18:13 【问题描述】:我是 GraphQL 新手,我认为它会自动执行此操作。
例如如果我获取帖子列表,然后打开单个帖子,则该帖子的数据已经在内存中。我希望 GraphQL 能够重用缓存中的数据,但它会发出另一个网络请求。
架构类似于:
type Query
posts: [Post]
post(id: ID): Post
我正在使用 React。在PostsRoute
,我有:
useQuery(gql`
query
posts
id
title
`);
在PostRoute
,我有:
useQuery(gql`
query
post(id: $postId)
id
title
`);
我需要为 Apollo 配置什么来自动使用缓存的数据吗?或者这是 Apollo 默认不支持的东西?
【问题讨论】:
这能回答你的问题吗? Apollo client cache doesn't work as I excpected 【参考方案1】:阿波罗 2 号
如果您使用的是 Apollo 2,那么您正在寻找的可能是 cacheRedirects。它用于拦截查询并使用缓存解决它。链接的文档实际上准确地解释了您的用例,因此我建议您查看它,但为了后代,这是我个人的做法(适应您的情况)。
在您实例化它时,在您的InMemoryCache
选项中,添加一个cacheRedirects
字段并为您的post
查询指定一个自定义解析器,如下所示:
const cache = new InMemoryCache(
cacheRedirects:
Query:
post: (_, id, getCacheKey) => getCacheKey(__typename: "Post", id),
,
,
);
这假设您帖子的__typename
是Post
。自定义解析器的第一个参数是 ROOT_QUERY
的结果,我们在这里不使用它。第二个参数是传递给查询的参数(此处为id: "some_id"
),第三个参数是上下文,包含client
、cache
和getCacheKey
。这里只有getCacheKey
对我们有用。该方法采用__typename
和id
,并在缓存中返回其键。
这样就完成了自定义解析器。现在,当您查询 post(id: some_id)
时,它将查看自定义解析器,接收缓存键并从缓存中返回与该键匹配的结果。
阿波罗 3 号
cacheRedirects
已在 Apollo 3 中删除,但使用 field policies 可以实现相同的功能。实例化InMemoryCache
的时候还是需要设置的,不过还是有点不一样:
const cache = new InMemoryCache(
typePolicies:
Query:
fields:
post: (_, args, toReference) => toReference(__typename: "Post", id: args.id),
,
,
,
);
我们在post
类型Query
上定义一个字段策略读取。请注意,第二个参数现在包括 args
和辅助实用程序。这包括toReference
,基本上就是新的getCacheKey
。
【讨论】:
以上是关于GraphQL/Apollo 客户端:如果查询是先前查询的子集,则从缓存中获取数据的主要内容,如果未能解决你的问题,请参考以下文章
Apollo 客户端和 graphQl 查询错误:“OrganizationWhereUniqueInput”类型的变量“$where”预期值
如何从 graphql apollo 客户端查询中获取/记录/捕获错误
React Native 上的 GraphQL Apollo 类型生成