我正在使用 ngrx 存储来维护应用程序状态,使用 normalizr 来展平来自 API 调用和 Immutable 的数据。到目前为止,它运行得非常好,但我正在处理一些更复杂的数据关系,我想知道如何继续构建商店。
为了简化事情,我有两组对象。会话和发票。
一位用户登录并可以查看他的会话列表。商店中的状态保存在一个对象中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;
}
(实体包含标准化输出 - 客户和导师是会话中包含的嵌套类型)
这真的很有效。减速器将其设置为加载,以便视图可以显示加载栏,然后填充数据,我可以以合理的平面方式使用它,引用映射数据中的 id。
他们可以加载发票,这与IInvoices
object:
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;
}
然而,现在我谈到了更复杂的关系。会话被分配给发票。有几种方法可以继续前进:
每个发票本身都可以有一个 ISessions 对象。这似乎违背了数据结构扁平化的想法。我还可能有重复会话,存储在 AppState.sessions 和 AppState.invoices 中。然而,管理起来会更容易,因为 IInvoice 更直接地映射到视图的状态(加载会话等存储在全部封装的发票 ISessions 对象中)。
我可以将 ISession 到发票 ID 的映射存储在商店中,与 ISession 和发票分开:
eg:
export interface IAppState {
sessions: ISessions;
invoices: IInvoices;
invoicesSessions: Map<number, ISessions>;
}
- 我可以将发票加载到现有的 ISessions 对象中。这意味着所有会话数据都位于同一位置,并且不存在重复。一个问题是我现在很难将其映射到视图。每张发票都必须获取会话列表,并过滤出仅需要的内容。我必须开始跟踪 ISessions 对象中发票会话的加载。
还有一个问题是,我是否应该存储两份单独的客户和导师列表,一份在 ISessions 中,一份在 IInvoices 中。像这样拆分商店是一个坏主意吗?这意味着我的减速器必须整体运行IAppState
对象而不是子部分。
基本上:当我获取数据时,我是否应该将其剥离并编译大型 ID 索引列表,然后让视图几乎“查询”他们需要的内容 - 基本上像数据库一样使用存储,或者我应该持有深层嵌套直接反映视图的对象集合 - 意味着数据经常在需要的地方重复多次?