在关于 设计状态形状的章节中,文档建议将您的状态保存在一个由 ID 键控的对象中:
以 ID 作为键保存对象中的每个实体,并使用 ID 从其他实体或列表中引用它。
他们进入了州立大学
把应用程序的状态想象成一个数据库。
我正在处理过滤器列表的状态形状,其中一些过滤器将打开(它们显示在一个弹出窗口中) ,或者有选择的选项。当我读到“将应用程序的状态看作一个数据库”时,我认为它们是一个 JSON 响应,因为它将从一个 API (它本身由一个数据库支持)返回。
所以我觉得
[{
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',
}
}
从理论上讲,它应该不会像 数据是可序列化的(在标题“状态”下)那样重要。
因此,我愉快地使用了对象数组方法,直到我开始编写我的约简程序。
使用 id 对象键控的方法(以及扩展语法的广泛使用) ,reduce 的 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)简化器的简单性是使用 id 键控对象方法的动机吗?这种状态形状还有其他优势吗?
还有
2)似乎对象键控的 id 方法使得处理 API 的标准 JSON 输入/输出变得更加困难。(这就是我一开始使用对象数组的原因。)因此,如果采用这种方法,是否仅仅使用函数在 JSON 格式和状态形状格式之间来回转换它?看起来很笨重。(不过,如果您支持这种方法,那么您是否认为这种方法比上面的对象数组简化器更简单呢?)
还有
3)我知道丹 · 阿布拉莫夫(Dan Abramov)设计了理论上的不可知状态-数据-结构的归约(按照惯例,顶级状态是一个对象或类似于 Map 的其他键值集合,但是从技术上讲,它可以是任何类型的 强调我的建议)。但是考虑到上述情况,是仅仅“建议”保持它是一个由 ID 键控的对象,还是使用一系列对象会遇到其他不可预见的痛点,使得我应该放弃那个计划并试图坚持使用 ID 键控的对象?