ApolloClient:如何处理缓存中的规范化/嵌套?

时间:2020-03-23 02:20:04

标签: apollo apollo-client

对于具有嵌套字段,我不清楚如何使用ApolloClient InMemoryCache。

例如,我有一个GraphQL突变,当将待办事项标记为“完成”时,也会将其所有子项标记为“已完成”。在后端,“子代”是“ parent_id”和“ id”之间的关系。

  "data": {
    "upsertTodos": [
      {
        "todo": {          
          "__typename": "rc_todos",
          "is_completed": true,
          "label": "Go to the store",
          "id": 1252,
          "parent_id": null
          "children": [
            {
              "__typename": "rc_todos",
              "id": 1040,
              "is_completed": true,
              "label": "Buy some milk",
              "parent_id": 1252
            }
          ],
        }
      }
    ]
  }
}

因此,这两个项目都是待办事项(与__typename相同),并且都具有id。我想确保缓存在嵌套和未嵌套状态下都能“理解”它们。

  1. ApolloClient是否可以“弄清楚”“ parent_id”与 “ id”或有什么我可以/应该做的事情,以确保它理解这一点以便处理 正常化和非正规化?
  2. 假设“购买一些牛奶”已从 查询ALL_TODOS迄今已获取所有待办事项的“固定”列表。如果我writeQuery反对ALL_TODOS,只是更新了“转到商店”待办事项(如上述响应中那样,在“儿童”中添加了“购买牛奶”),那么缓存是否知道“根级别” ““买点牛奶”待办事项应该更新吗? (因为它发现__typenameid相同)还是我需要在突变的更新函数中手动进行一些转换才能使其起作用?
  3. 一般而言,在以下情况下应遵循“最佳做法” 使用InMemoryCache处理有时需要查询的数据 以这种方式“平坦”,有时是“嵌套”?

1 个答案:

答案 0 :(得分:1)

缓存仅通过存储对服务器返回的对象的引用来标准化响应中的数据。如果一个字段解析为一个对象,则该对象将被拉出并分别缓存,并且该字段的值将只是对该对象的引用(即,通过组合__typename和{{1}创建的缓存键}字段)。如果一个字段解析为一个对象列表,则列表中的每个对象将被拉出并分别缓存,并且该字段的值将只是对每个对象的引用的数组。

由于对象是根据上述缓存键进行缓存的,因此如何并不重要,查询将返回特定的对象-如果对象在响应中,它将覆盖已存在的对象缓存。任何父母/子女关系都与该机制无关。手动写入缓存也是如此。

当您仅对已在缓存中的对象进行突变时,关键是服务器在响应中某个位置返回该突变的对象-只要这样做,缓存将被更新以反映任何更改被制成物体。

棘手的是影响对象在列表中成员资格的变异。例如,您可能有一个查询返回一个已完成的待办事项列表,而另一个查询返回一个待处理的待办事项列表。缓存将为每个与适当的待办事项对象匹配的查询存储一个缓存键数组。如果某个突变将待办事项的状态从待处理更改为完成,则Apollo无法知道需要将其从一个查询中删除并将其添加到另一个查询中(这是只有您的服务器才知道的业务逻辑)。在这种情况下,我们必须手动写入缓存并自己更新查询。

相同的原则适用于创建或删除待办事项-Apollo无法知道“此突变已创建待办事项”,即使这样做,也无法知道应将其添加到哪个列表中。