将每个实体保存在以ID为键的对象中,并使用ID从其他实体或列表引用它。
他们继续说道:
把应用程序的状态想象成一个数据库。
我正在为一系列过滤器的状态形状工作,其中一些过滤器将是打开的(它们显示在弹出窗口中),或者具有选定的选项。当我读到“把应用程序的状态想象成一个数据库”时,我考虑将它们视为从API返回的JSON响应(本身由数据库支持)。
所以我想到了这样:
[{
id: '1',
name: 'View',
open: false,
options: ['10', '11', '12', '13'],
selectedOption: ['10'],
parent: null,
},
{
id: '10',
name: 'Time & Fees',
open: false,
options: ['20', '21', '22', '23', '24'],
selectedOption: null,
parent: '1',
}]
然而,文档建议使用更像以下格式
{
1: {
name: 'View',
open: false,
options: ['10', '11', '12', '13'],
selectedOption: ['10'],
parent: null,
},
10: {
name: 'Time & Fees',
open: false,
options: ['20', '21', '22', '23', '24'],
selectedOption: null,
parent: '1',
}
}
在理论上,只要数据可序列化(在“状态”标题下),那么它就不应该有影响。
因此,我很高兴地采用了对象数组的方法,直到我写reducer时。
使用以id为键的对象方法(并大量使用展开语法),reducer的
OPEN_FILTER
部分变成:switch (action.type) {
case OPEN_FILTER: {
return { ...state, { ...state[action.id], open: true } }
}
与对象数组的方法相比,这种方法更冗长(且依赖于辅助函数)。
switch (action.type) {
case OPEN_FILTER: {
// relies on getFilterById helper function
const filter = getFilterById(state, action.id);
const index = state.indexOf(filter);
return state
.slice(0, index)
.concat([{ ...filter, open: true }])
.concat(state.slice(index + 1));
}
...
我的问题有三个:
1)reducer的简单性是采用基于ID的对象键方法的动机吗?这种状态形式还有其他优点吗?
和
2)基于ID的对象键方法似乎使处理标准JSON的API更加困难。(这就是我首先选择对象数组的原因。)那么,如果你采用这种方法,你只是使用一个函数在JSON格式和状态形式格式之间进行转换吗?那看起来很笨重。(尽管如果你支持这种方法,你的理由部分是认为这比上面的对象数组reducer不那么笨重?)
和
3)我知道Dan Abramov设计redux的理论目标是使其与状态数据结构无关(如"按照惯例,顶层状态是一个对象或其他像Map这样的键值集合,但从技术上讲它可以是任何类型",强调是我的)。但鉴于上述情况,将其保持为以ID为键的对象只是“推荐”,还是我会遇到其他未预见的痛点,使我应该放弃这个计划,尝试坚持以ID为键的对象?
sort_by
这样的东西之外?const sorted = _.sortBy(collection, 'attribute');
- nickcoxdotme