突变后如何使Relay的缓存失效

Posted

技术标签:

【中文标题】突变后如何使Relay的缓存失效【英文标题】:How to invalidate Relay's cache after mutation 【发布时间】:2018-01-03 20:01:40 【问题描述】:

我正在使用 React/Relay/GraphQL 重建一个小型内部 Web 应用程序以熟悉此堆栈。基本上,它监控“活动”视频列表的分析。唯一的变化是将活动视频 ID 列表替换为新列表。 问题在于,替换 ID 后,Relay 继续传递旧的 ID 列表而不是新的。

我无法弄清楚如何操作传递给commitMutation()updateroptimisticUpdater 回调的商店。我只需要清除存储的活动视频列表,以便它知道调用一个新视频,或者让它重新运行 graphql 查询以刷新缓存。

具体来说,我需要清除此查询的结果:

const ActiveVideosQuery = graphql`
    query App_ActiveVideos_Query 
        activeVideos 
            ...SetActiveVideosPage_activeVideos
            ...VideoList_activeVideos
        
    
`

突变(TypeScript):

const  commitMutation, graphql  = require('react-relay')


const mutation = graphql`
    mutation SetActiveVideosMutation($input: SetActiveVideosInput!) 
        setActiveVideos(input: $input) 
            clientMutationId
        
    
`

let nextClientMutationId = 0

function commit(environment, ids: string[]) 
    const clientMutationId = nextClientMutationId++

    return commitMutation(environment, 
        mutation,
        variables:  input:  ids, clientMutationId  ,
    )



export default  commit 

还有架构:

type Channel 
  id: ID!
  name: String!


type Mutation 
  setActiveVideos(input: SetActiveVideosInput!): SetActiveVideosPayload


type Query 
  activeVideos: [Video]!


input SetActiveVideosInput 
  ids: [ID]!
  clientMutationId: String!


type SetActiveVideosPayload 
  clientMutationId: String!


type Video 
  id: ID!
  active: Boolean!
  details: VideoDetails
  statsByAge(seconds: Int!): [VideoStats]!


type VideoDetails 
  title: String!
  description: String!
  thumbnailURL: String!
  publishedAt: String!
  channel: Channel!


type VideoStats 
  videoID: ID!
  recordedAt: String!
  views: String!
  likes: String!
  dislikes: String!
  favorites: String!
  comments: String!

【问题讨论】:

【参考方案1】:

你会想要使用The Relay "Environment"。

中继“环境”将中继运行所需的配置、缓存存储和网络处理捆绑在一起。

Question:为什么没有一个命令 Relay.reset() 可以简单地从应用程序中擦除所有内容?

Answer: 因为只实例化一个新的 Relay.Environment() 比试图确保你已经清理了全局单例 Relay.Store 上的所有内容要干净得多。

编辑:回应您的评论;

Relay 目前提供了对何时重新获取数据的非常粗粒度的控制:primeCache 默认使用内存中的数据来完成查询,而 forceFetch 绕过缓存并从服务器完全重新获取数据。同样,在实践中,这对于我们的大多数用例都非常有效。

重新获取和缓存驱逐控制 view issue

关于缓存驱逐,重要的是要了解 Relay 与许多典型的缓存根本不同。典型的缓存存储独立的键/值对,而 Relay 缓存互连对象的图。我们在 Thinking in GraphQL 中广泛介绍了这一点的影响。在实践中,这意味着缓存驱逐的简单方法(例如 TTL 或 LRU)可能会产生不直观的后果。例如,产品通常关心查询,而缓存存储规范化的记录。如果甚至从缓存中逐出一条记录,它可能会导致整个查询有效地“丢失”并需要重新获取。此外,应用程序的离散部分的数据依赖关系可能会重叠,因此它们在数据的允许陈旧性方面存在分歧。

【讨论】:

虽然我认为这可能适用于只有一个查询的特定实例,但如果我只想重置缓存的一部分,只是 query activeVideos ... 的结果,而不是每个询问? (我也对如何将新环境引入系统感到困惑,但我认为这超出了这个问题的范围,因为我正在使用 foundfound-relay。) 感谢您添加的详细信息。这就说得通了。现在我只需要弄清楚如何使用found 来做到这一点。 如何将此解决方案与 found 集成的非常明显的答案是将 found 的路由器组件包装在另一个组件中,该组件在需要时传递一个新的解析器。仍在学习用 React 思考...... HoC 很棒

以上是关于突变后如何使Relay的缓存失效的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Relay Modern 突变进行文件上传?

如何进行示例 GraphQL Relay 突变

如何订阅relay/graphql突变的进度事件

Graphcool 登录后更新 Relay 存储

如何正确地使在线/离线 Web 应用程序的 HTML5 缓存清单失效?

React-relay 嵌套突变后未获得有效负载