如何使用深度嵌套查询处理 Vue Apollo 中的删除?

Posted

技术标签:

【中文标题】如何使用深度嵌套查询处理 Vue Apollo 中的删除?【英文标题】:How do I handle deletes in Vue Apollo with deeply nested queries? 【发布时间】:2017-08-04 18:16:00 【问题描述】:

我有一个查询,它返回多个嵌套对象以呈现一个充满信息的屏幕。我想删除一个深度嵌套的对象并乐观地更新屏幕(即不运行完整的查询)。

为了解释查询和 UI,我将使用类似 Trello board 的查询作为示例:

query everything 
  getBoard(id: "foo") 
    name
    cardLists         
      edges 
        node 
          id
          name
          cards 
            edges 
              node 
                id
                name
              
            
          
        
      
    
  

此查询的结果用于构建这样的 UI:https://d3uepj124s5rcx.cloudfront.net/items/170a0V1j0u0S2p1l290I/Board.png

我正在使用以下方式构建应用程序:

VueJS Vue 阿波罗 Scaphold.io 作为我的 GraphQL 商店

当我想删除其中一张卡片时,我会调用:

deleteCard: function () 
  this.$apollo.mutate(
    mutation: gql`
      mutation deleteCard($card: DeleteCardInput!) 
        deleteCard(input: $card) 
          changedCard 
            id
          
        
      
    `,
    variables: 
      'card': 
        id: this.id
      
    ,
  )
  .then(data => 
    // Success
  )

突变成功删除卡片,但我想根据突变立即更新 UI。执行此操作的简单选项是调用 refetchQueries: ['everything'] — 但这是一个昂贵的查询,而且对于快速 UI 更新来说太慢了。

我想做的是乐观地更新 UI,但是 Vue Apollo 的 example mutations 既没有解决删除问题,也没有解决深度嵌套的场景。

从深度嵌套的查询中删除项目并乐观地更新 UI 的正确解决方案/最佳实践是什么?

【问题讨论】:

如何在突变后更新查询,使用 updateQueries 或 apollo 客户端的 dataIdFromObject 属性? @Locco0_0 - 我正在使用updateQueries。我是否可以使用dataIdFromObject 直接从商店中删除该对象,而不是更新查询? 是的,如果您向突变的返回值添加更深的嵌套,例如添加 cardLists 的 id 并在其中添加卡片。但它当然更慢。 【参考方案1】:

如果您查看 apollo 的 optimistic Response 的文档,您会发现乐观响应“伪造”了突变结果。

因此它将处理具有乐观值的updateQueries 函数。在您的情况下,这意味着如果您添加 optimisticResponse 属性,它应该使用乐观值更改 apollo 存储中的查询:

可能是这样的:

this.$apollo.mutate(
  mutation: gql `
      mutation deleteCard($card: DeleteCardInput!) 
        deleteCard(input: $card) 
          changedCard 
            id
          
        
      
    `,
  variables: 
    'card': 
      id: this.id
    
  ,
  updateQueries: 
    // .... update Board
  ,
  optimisticResponse: 
    __typename: 'Mutation',
    deleteCard: 
      __typename: 'Card', // graphQL type of the card
      id: this.id,
    ,
  ,
)

【讨论】:

谢谢。我不清楚的一点是如何编写updateQueries,以便我可以非常有效地从现有查询中删除适当的节点,而不是再次重新查询整个板,这很慢。 我明白了。然后你可能想寻找reacts immutability helper。然后,您必须在深层嵌套查询中搜索正确的元素。看起来很硬 感谢指点,我去看看。我正在使用 Vue,但阅读 React 的不变性助手可能会帮助我了解情况。 与此同时,我意识到我可以轻松地在突变查询中加载父列表(以及子卡),让 Apollo 自动更新 UI。这仍然是一个过于昂贵的查询,但比重新加载整个董事会要好。 是的,我想加载这么多树的成本太高了。但正如你所说,总比重新取整板要好。

以上是关于如何使用深度嵌套查询处理 Vue Apollo 中的删除?的主要内容,如果未能解决你的问题,请参考以下文章

Nuxt(Vue) 使用 $apollo.query 处理 Apollo 错误

Rails 使用 JSON 将深度嵌套属性到 Vue 实例

如何处理 Vue.JS 中的 Apollo Graphql 查询错误?

TypeORM Apollo 嵌套查询解析器

如何在 Vue 组件事件中触发 Apollo 查询?

如何通过 ID 从 Apollo 缓存中读取嵌套对象?