构建状态管理存储 (ngrx/redux)。扁平代表数据,还是嵌套代表视图?

Structuring state management store (ngrx/redux). Flat as representative of data, or nested as representative of view?

我正在使用 ngrx 存储来维护应用程序状态,使用 normalizr 来展平来自 API 调用和不可变的数据。到目前为止,它一直运行良好,但我遇到了一些更复杂的数据关系,我想知道如何继续构建商店。

为了简单起见,我有两组对象。会话和发票。

一个用户登录并可以查看他的会话列表。商店中的状态保存在一个对象中 ISessions:

export interface ISessions extends Map<String, any> {
  result: List<Number>;
  entities: {
    sessions: Map<Number, ISessions>,
    clients: Map<Number, IClient>,
    tutors: Map<Number, IProfile>
  },
  adding: boolean;
  loading: boolean;
  loadingFailed: boolean;
  error: string;
}

(实体包含标准化输出 - 客户和导师是会话中包含的嵌套类型)

这真的很好用。 reducer 将其设置为加载,以便视图可以显示加载栏,然后填充数据我可以在映射数据中以合理的平面方式引用 id 来使用它。

他们可以加载发票,这与 IInvoices 对象非常相似:

export interface IInvoices extends Map<String, any> {
  result: List<Number>;
  entities: {
    invoices: Map<Number, IInvoice>,
    clients: Map<Number, IClient>,
    tutors: Map<Number, IProfile>
  },
  adding: boolean;
  loading: boolean;
}

所以我的商店是这样的:

export interface IAppState {
  sessions: ISessions;
  invoices: IInvoices;
}

但是,现在我谈到了更复杂的关系。会话分配给发票。有几种前进的方式:

  1. 每个发票本身都可以有一个 ISessions 对象。这似乎违背了让数据结构扁平化的想法。我也可能有重复会话,存储在 AppState.sessions 和 AppState.invoices 中。然而,由于 IInvoice 更直接地映射到视图的状态(加载会话等存储在发票 ISessions 对象中,所有封装),它会更容易管理。

  2. 我可以将 ISessions 映射存储在商店中的发票 ID 中,分别存储到 ISessions 和发票:

例如:

export interface IAppState {
  sessions: ISessions;
  invoices: IInvoices;
  invoicesSessions: Map<number, ISessions>;
}
  1. 我可以将发票加载到现有的 ISessions 对象中。这意味着所有会话数据都在同一个地方,并且没有重复。一个问题是我现在很难将它映射到视图。每张发票都必须获取会话列表并过滤出它所需要的。我必须开始跟踪 ISessions 对象中发票会话的加载。

还有一个问题是我是否应该存储两个单独的客户和导师列表,一个在 ISessions 中,一个在 IInvoices 中。像这样拆分商店是个坏主意吗?这意味着我的 reducer 必须对整个 IAppState 对象而不是子部分进行操作。

基本上:当我获取数据时,我是否应该将其剥离并编译大的 ID 索引列表,然后让视图几乎 'query' 他们需要的东西 - 基本上像数据库一样使用商店或者应该我持有一个直接反映视图的深层嵌套对象集合 - 这意味着数据经常在需要的地方重复多次?

是的,推荐的构建 Redux 存储的方法是根据数据而不是视图来构建状态形状,对于关系数据的建议是保持所有规范化。使用选择器函数作为对该状态的查询。

有关详细信息,请参阅:

另外,我的"Practical Redux" tutorial series shows how to use the Redux-ORM library to manage relational data in your Redux state: Practical Redux-ORM Basics and Practical Redux, Part 2: Redux-ORM Concepts and Techniques