ApolloClient:你如何处理缓存中的规范化/嵌套?
ApolloClient: How do you handle normalization / nesting in the cache?
对于具有嵌套的字段,我不清楚如何使用 ApolloClient InMemoryCache。
例如,我有一个 GraphQL 突变,在标记待办事项时 "completed," 也会标记其所有子项 "completed." 在后端,"child" 是"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
。我想确保缓存 "understands" 它们处于嵌套和未嵌套状态。
- ApolloClient "figure out"和"parent_id"的关系可以吗
"id" 或者我可以/应该做些什么来确保它理解这一点以便处理
规范化和反规范化正确吗?
- 假设 "Buy some milk" 已经从
查询
ALL_TODOS
到目前为止已经获取了所有待办事项的 "flat" 列表。如果我 writeQuery
反对 ALL_TODOS
只是更新 "Go to the store" 待办事项 - 在 "children" 中使用 "Buy some milk",如上面的响应 - 缓存是否理解 "root level" "Buy some milk" todo 应该更新? (因为它看到 __typename
和 id
是相同的)或者我需要在突变的更新函数中手动做一些转换才能工作吗?
- 一般来说,有没有"best practices"
使用 InMemoryCache 处理有时会查询的数据
"flat" 有时 "nested" 以这种方式?
缓存通过仅存储对服务器 return 编辑的对象的引用来规范化来自响应的数据。如果一个字段解析为一个对象,该对象将被拉出并单独缓存,该字段的值将只是对该对象的引用(即通过组合 __typename
和 [=11= 创建的缓存键) ] 字段)。如果一个字段解析为对象列表,列表中的每个对象将被拉出并单独缓存,字段的值将只是每个对象的引用数组。
由于对象是根据上述缓存键进行缓存的,因此如何查询return一个特定对象并不重要——如果该对象位于响应,它将覆盖缓存中已有的内容。任何 parent/child 关系都与机制无关。手动写入缓存也是如此。
当你只是改变一个已经在缓存中的对象时,关键是服务器要return它响应中某处的变异对象——只要它这样做,缓存就会更新以反映对对象所做的任何更改。
棘手的是影响对象在列表中的成员资格的突变。例如,您可能有一个 return 是已完成待办事项列表的查询,而另一个 return 是未决待办事项列表的查询。缓存将为匹配适当的待办事项对象的每个查询存储一个缓存键数组。如果突变将待办事项的状态从待办事项更改为已完成,Apollo 无法知道它需要将其从一个查询中删除并将其添加到另一个查询中(这是只有您的服务器知道的业务逻辑)。在这种情况下,我们必须手动写入缓存并自行更新查询。
相同的原则适用于创建或删除待办事项——Apollo 无法知道 "this mutation created a todo",即使它知道,也无法知道应该将其添加到哪些列表。
对于具有嵌套的字段,我不清楚如何使用 ApolloClient InMemoryCache。
例如,我有一个 GraphQL 突变,在标记待办事项时 "completed," 也会标记其所有子项 "completed." 在后端,"child" 是"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
。我想确保缓存 "understands" 它们处于嵌套和未嵌套状态。
- ApolloClient "figure out"和"parent_id"的关系可以吗 "id" 或者我可以/应该做些什么来确保它理解这一点以便处理 规范化和反规范化正确吗?
- 假设 "Buy some milk" 已经从
查询
ALL_TODOS
到目前为止已经获取了所有待办事项的 "flat" 列表。如果我writeQuery
反对ALL_TODOS
只是更新 "Go to the store" 待办事项 - 在 "children" 中使用 "Buy some milk",如上面的响应 - 缓存是否理解 "root level" "Buy some milk" todo 应该更新? (因为它看到__typename
和id
是相同的)或者我需要在突变的更新函数中手动做一些转换才能工作吗? - 一般来说,有没有"best practices" 使用 InMemoryCache 处理有时会查询的数据 "flat" 有时 "nested" 以这种方式?
缓存通过仅存储对服务器 return 编辑的对象的引用来规范化来自响应的数据。如果一个字段解析为一个对象,该对象将被拉出并单独缓存,该字段的值将只是对该对象的引用(即通过组合 __typename
和 [=11= 创建的缓存键) ] 字段)。如果一个字段解析为对象列表,列表中的每个对象将被拉出并单独缓存,字段的值将只是每个对象的引用数组。
由于对象是根据上述缓存键进行缓存的,因此如何查询return一个特定对象并不重要——如果该对象位于响应,它将覆盖缓存中已有的内容。任何 parent/child 关系都与机制无关。手动写入缓存也是如此。
当你只是改变一个已经在缓存中的对象时,关键是服务器要return它响应中某处的变异对象——只要它这样做,缓存就会更新以反映对对象所做的任何更改。
棘手的是影响对象在列表中的成员资格的突变。例如,您可能有一个 return 是已完成待办事项列表的查询,而另一个 return 是未决待办事项列表的查询。缓存将为匹配适当的待办事项对象的每个查询存储一个缓存键数组。如果突变将待办事项的状态从待办事项更改为已完成,Apollo 无法知道它需要将其从一个查询中删除并将其添加到另一个查询中(这是只有您的服务器知道的业务逻辑)。在这种情况下,我们必须手动写入缓存并自行更新查询。
相同的原则适用于创建或删除待办事项——Apollo 无法知道 "this mutation created a todo",即使它知道,也无法知道应该将其添加到哪些列表。