我正在使用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;
}
(实体包含规范化输出 - 客户端和导师是会话中包含的嵌套类型)
这非常有效。 reducer将其设置为加载,以便视图可以显示加载条,然后填充数据我可以在引用映射数据中的id的合理平坦的mannor中使用它。
他们可以加载发票,这在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;
}
然而,现在我来到了更复杂的关系。会话分配给发票。有几种方法可以推进:
每个发票本身都有一个ISessions对象。这似乎违背了使数据结构平坦的想法。我也可能有重复的会话,存储在AppState.sessions和AppState.invoices中。然而,它更容易管理,因为IInvoice更直接映射到视图的状态(加载会话等存储在所有封装的发票ISessions对象中)。
我可以将商店的发票ID的ISessions地图分别存储到ISessions和发票中:
例如:
export interface IAppState {
sessions: ISessions;
invoices: IInvoices;
invoicesSessions: Map<number, ISessions>;
}
还有一个问题是我是否应该存储两个单独的客户和导师列表,一个在ISessions中,一个在IInvoices中。像这样拆分商店是个坏主意吗?这意味着我的减速器必须在整个IAppState
对象而不是子部分上运行。
基本上:当我获取数据时,我是否应该将其剥离并编译大型ID索引列表,让视图几乎“查询”他们需要的东西 - 基本上像数据库一样使用商店或者我应该持有直接反映视图的深层嵌套对象 - 意味着数据经常在多次需要的地方重复?
答案 0 :(得分:10)
是的,构建Redux商店的推荐方法是根据数据而不是视图来建立状态形状,对关系数据的建议是将其全部规范化。使用选择器函数作为对该状态的查询。
有关详细信息,请参阅:
此外,我的"Practical Redux" tutorial series显示了如何使用Redux-ORM库管理Redux状态中的关系数据:Practical Redux-ORM Basics和Practical Redux, Part 2: Redux-ORM Concepts and Techniques。