自动缓存更新在 react apollo 中不起作用

Posted

技术标签:

【中文标题】自动缓存更新在 react apollo 中不起作用【英文标题】:Automatic cache updates do not work in react apollo 【发布时间】:2018-09-11 21:16:32 【问题描述】:

document 表示缓存可以在以下示例中自动更新:


  post(id: '5') 
    id
    score
  


mutation 
  upvotePost(id: '5') 
    id
    score
  

当缓存对象在列表中时,自动更新会在以下情况下工作吗?像这样:

这是一个获取评论列表的查询:


  reviewList(model:12)
    list
      reviewId
      text
    
    cursor
  

当我将列表中的一条评论更新到服务器时,react apollo 不会自动更新缓存的评论:

mutation
  updateReview(reviewId:'1',text:'new text')
     reviewId
     text
  

是否必须使用突变组件的update属性来更新缓存?

【问题讨论】:

【参考方案1】:

假设您使用的是apollo-cache-inmemory,除非您要在列表中添加项目或从列表中删除项目,否则不需要使用更新。但是,重要的是要记住缓存数据是标准化的,并且 Apollo 利用__typenameid(或_id)字段为任何查询对象生成缓存键。来自文档:

InMemoryCache 在将数据保存到存储之前对其进行规范化 通过将结果拆分为单个对象,创建一个独特的 每个对象的标识符,并将这些对象存储在展平的 数据结构。默认情况下,InMemoryCache 将尝试使用 常见的 id 和 _id 的主键作为唯一标识符 if 它们与对象上的 __typename 一起存在。

如果缺少id 字段,Apollo 将不知道如何匹配查询中的数据和突变中的数据:

如果没有指定 id 和 _id,或者如果没有指定 __typename, InMemoryCache 将回退到查询中对象的路径, 例如 ROOT_QUERY.allPeople.0 用于返回的第一条记录 allPeople 根查询。这将使给定类型的数据范围为 allPeople 查询和其他查询必须自己获取 分开的对象。

幸运的是,有一个解决方法。您当然可以在服务器端将reviewId 重命名为id。但是,如果您希望缓存只使用 reviewId 字段,则可以将 dataIdFromObject 函数传递给您的 InMemoryCache 构造函数:

import  InMemoryCache, defaultDataIdFromObject  from 'apollo-cache-inmemory'

const cache = new InMemoryCache(
  dataIdFromObject: object => 
    switch (object.__typename) 
      case 'Review': return object.reviewId
      default: return defaultDataIdFromObject(object)
    
  
)

只要结果值是唯一的,您就可以以类似的方式使用任何其他字段(或字段组合)。

【讨论】:

以上是关于自动缓存更新在 react apollo 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用`react-apollo-hooks`和`useSubscription`钩子时如何避免“自动更新”缓存

React Apollo:添加新项目时更新列表缓存(带变量)

React Apollo 在突变后更新客户端缓存

Apollo resetStore 在 Angular 客户端中不起作用

为啥需要更新器/更新函数来更新 React Relay 和 Apollo 客户端中的本地缓存?

如何在 React Apollo 2.0 中正确地重新获取和缓存更新的数据?