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),
    ,
  ,
);

这假设您帖子的__typenamePost。自定义解析器的第一个参数是 ROOT_QUERY 的结果,我们在这里不使用它。第二个参数是传递给查询的参数(此处为id: "some_id"),第三个参数是上下文,包含clientcachegetCacheKey。这里只有getCacheKey 对我们有用。该方法采用__typenameid,并在缓存中返回其键。

这样就完成了自定义解析器。现在,当您查询 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 客户端查询中获取/记录/捕获错误

带有 GraphQL Apollo 客户端的订阅组件

React Native 上的 GraphQL Apollo 类型生成

TypeError:试图分配给只读属性。在 Expo / GraphQL Apollo 客户端上

如何在 GraphQL apollo-android 客户端中获取 HTTP 状态码