0

来自Redux 文档

这种 [标准化] 状态结构总体上要平坦得多。与原来的嵌套格式相比,这是在几个方面的改进......

来自https://github.com/paularmstrong/normalizr

许多 API,无论是否公开,都返回具有深度嵌套对象的 JSON 数据。对于 JavaScript 应用程序,尤其是使用 Flux 或 Redux 的应用程序,使用这种结构的数据通常非常困难。

似乎规范化的数据库式数据结构更适合在前端使用。那么,如果 GraphQL 的整个语言风格都围绕着快速获取任何嵌套数据,为什么它如此受欢迎呢?那为什么人们会使用它呢?

4

2 回答 2

0

这种讨论是题外话...

这不仅仅是关于 [规范化] 结构......

graphql客户端(如 apollo)负责所有与数据获取相关的细微差别(错误处理、缓存、重新获取、数据转换等),但在 redux 中几乎无法实现。

不同的用例,您可以同时使用

  • 在 redux 中保持(复杂)应用程序状态,
  • 处理 apollo 中的数据获取(您也可以将其用于本地状态)。
于 2020-08-16T09:37:49.263 回答
0

让我们看看我们为什么要规范化缓存,以及我们必须做什么样的工作才能获得规范化的缓存。

对于主页,我们获取一个 TODO 列表和一个高优先级 TODOS 列表。我们的两个端点返回以下数据:

{
  all: [{ id: 1, title: "TODO 1" }, { id: 2, title: "TODO 2" }, { id: 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, title: "TODO 1" },
    "Todo:2": { id: 2, title: "TODO 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]),
  };
}

请注意Todo:1,如果我们在 React 组件内部运行此函数(这通常在 Redux 中称为选择器),那么现在在缓存内部更新将如何自动更新所有引用 todo 的查询。

GraphQL 的神奇之处在于它是一个带有类型系统的严格规范。这允许像 Apollo 这样的 GraphQL 客户端全局识别对象并规范化该缓存。同时它还可以自动为你去规范化缓存,并在突变后自动更新缓存中的对象。这意味着大多数时候您根本不需要编写缓存逻辑。这应该可以解释为什么它如此受欢迎:最好的代码就是没有代码!

const { data, loading, error } = useQuery(gql`
  { all { id title } highPrio { id title }
`);

此代码在加载时自动获取查询,规范化响应并将其写入缓存。然后使用缓存数据将缓存非规范化回查询的形状。对缓存中元素的更新会自动更新所有订阅的组件。

于 2020-10-13T22:55:13.240 回答