如何强制 Apollo 客户端将缓存数据用于详细视图页面

Posted

技术标签:

【中文标题】如何强制 Apollo 客户端将缓存数据用于详细视图页面【英文标题】:How to force Apollo Client to use cached data for detail view page 【发布时间】:2021-01-28 15:54:56 【问题描述】:

我有一个基于分页游标的查询 TODOS 和带有查询 TODO 的详细信息页面,以按 ID 获取数据。 每当我转到详细视图并将 useQueryTODO 查询一起使用时(其中包含与 TODOS 查询结果完全相同的数据,它仍然会尝试获取数据从服务器而不是从缓存。我怎样才能实现不从服务器获取数据(因为它已经存在),我认为 Apollo 通过 id 检测并从缓存返回但没有。有什么建议吗?

类似的问题没有这个post,但我认为这不是一个正确的方法,应该有更好的解决方案。 (希望)

这是TODOS查询:

query TODOS(
  $paginationOptions: PaginationOptionsInput
) 
  todos(paginationOptions: $paginationOptions) 
    pagination 
      minCursor
      maxCursor
      sortOrder
      limit
      hasMoreResults
    
    result 
     id
     ...SomeTodoFields
  

在详细信息页面上我有第二个查询TODO

query (
  $todoId: String!
) 
  todo(todoId: $todoId) 
    id
    ...SomeTodoFields
   

【问题讨论】:

你能发布一些代码,以便我们给你一些指导吗? ApolloClient 旨在在进行任何查询之前先查看缓存,除非您明确告诉它不要使用缓存 - 您可能正在做一些意想不到的事情,导致缓存被忽略。 马上更新 如果分页TODOS查询和单个TODO查询下的字段相同,不应该从缓存中返回还是需要一些额外的配置来实现? 所以您需要检查的主要内容是从您的 TODO 查询结果返回的 __typename 以及您的 TODOS 查询的结果部分。这个想法是,如果 __typenames 与这些对象匹配,那么 ApolloClient 能够确定它们是相同的,从而执行正确的缓存查询。我的建议是将 __typename 字段添加到每个查询中,并将结果作为第一步进行比较。 __typename 有点不同,因为 TODOS 查询是分页的,它返回 paginatedTodosType 作为根 __typename 并且它有结果字段 - __typeName 数组:todoType。当我获取 TODO 查询时,我得到 __typeName: todoType 的单个对象 【参考方案1】:

由于我使用 Apollo-client here。仔细阅读每一个音符,这真的很重要!我的代码示例:

cache: new InMemoryCache(
    fragmentMatcher,
    cacheRedirects: 
      Query: 
        todo: (_, args,  getCacheKey ) => 
          return getCacheKey( __typename: 'TodoType', id: args.todoId )
        
      
    

  )
)

还发现了一些很好的相关article,您可能想检查一下。 这对我有用,希望对其他人也有帮助。 :)

【讨论】:

以上是关于如何强制 Apollo 客户端将缓存数据用于详细视图页面的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL + Apollo - 如何强制进行查询,似乎正在缓存一些东西

GraphQL:Apollo 客户端缓存如何工作以保持与服务器的数据一致性?

使用 Apollo 链路状态缓存实现客户端过滤

查询后如何更新 Apollo 缓存?

缓存对象上的 Apollo 客户端查询重复数据删除

在 Apollo 客户端上更新缓存