如何解决GraphQL与标准化数据结构的优势
来自Redux docs:
此[规范化]状态结构总体而言要平坦得多。相比 原始的嵌套格式,这是一种改进,在几种方面...
来自https://github.com/paularmstrong/normalizr :
许多公共或非公共API都返回具有深度嵌套对象的JSON数据。 使用这种结构的数据通常非常困难,对于JavaScript应用程序,尤其是那些使用Flux或Redux的应用程序。
好像标准化的数据库式数据结构最好在前端使用。那么,如果GraphQL的全部语言风格都围绕快速获取任何嵌套数据而为何如此流行呢?那为什么人们要使用它?
解决方法
这种讨论在SO ...上是没有主题的
不仅与[规范化]结构有关 ...
graphql
客户端(如apollo)负责处理所有与数据获取相关的细微差别(错误处理,缓存,重新获取,数据转换等),但几乎无法与redux一起使用。
不同的用例,您可以同时使用:
- 在redux中保持(复杂)应用程序状态,
- 处理阿波罗中的数据获取(您也可以将其用于本地状态)。
让我们看看为什么要规范化缓存,以及我们要做什么样的工作才能获得规范化的缓存。
对于主页,我们获取一个TODO列表和一个高优先级TODOS列表。我们的两个端点返回以下数据:
{
all: [{ id: 1,title: "TODO 1" },{ id: 2,title: "TODO 2" },title: "TODO 2"}],highPrio: [{ id: 1,title: "TODO 1" }]
}
如果将这样的数据存储到缓存中,我们将很难更新单个待办事项,因为我们必须更新商店中或将来可能存在的每个阵列中的待办事项。
我们可以规范化数据,仅将引用存储在数组中。这样,我们可以轻松地在单个位置更新单个待办事项:
{
queries: {
all: [{ ref: "Todo:1" },{ ref: "Todo:2" },{ ref: "Todo:2" }],highPrio: [{ ref: "Todo:1" }}]
},refs: {
"Todo:1": { id: 1,"Todo:2": { id: 2,"Todo:3": { id: 3,title: "TODO 3" }
}
}
不利的一面是,现在很难在我们的列表组件中使用这种形状的数据了。我们将不得不对缓存进行很多转换,大致是这样:
function denormalise(cache) {
return {
all: cache.queries.all.map(({ ref }) => cache.ref[ref]),highPrio: cache.queries.highPrio.map(({ ref }) => cache.ref[ref]),};
}
请注意,如果我们在React组件(在Redux中通常称为选择器)中运行此函数,那么现在在缓存内部更新Todo:1
会如何自动更新所有引用待办事项的查询。
GraphQL的神奇之处在于它是对类型系统的严格规范。这使GraphQL客户端(如Apollo)可以全局标识对象并标准化该缓存。同时,它还可以为您自动使缓存规范化,并在发生突变后自动更新缓存中的对象。这意味着大多数时候您根本不需要编写缓存逻辑。这应该可以解释为什么它如此流行:最好的代码就是没有代码!
const { data,loading,error } = useQuery(gql`
{ all { id title } highPrio { id title }
`);
此代码在加载时自动获取查询,对响应进行规范化并将其写入缓存。然后使用缓存数据将缓存反规范化为查询的形状。对缓存中元素的更新会自动更新所有已订阅的组件。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。