nic*_*tme 87 javascript spread-syntax redux
在设计状态形状的章节中,文档建议将您的状态保存在由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',
}]
Run Code Online (Sandbox Code Playgroud)
但是,文档建议更像一种格式
{
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',
}
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,只要数据是可序列化的(在"状态"标题下)就没关系.
所以我愉快地使用了对象阵列方法,直到我写了我的减速器.
使用object-keyed-by-id方法(以及扩展语法的自由使用),OPEN_FILTERreducer 的一部分变为
switch (action.type) {
case OPEN_FILTER: {
return { ...state, { ...state[action.id], open: true } }
}
Run Code Online (Sandbox Code Playgroud)
使用对象数组方法,它更冗长(和辅助函数依赖)
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));
}
...
Run Code Online (Sandbox Code Playgroud)
1)减速器的简单性是否采用对象键控id方法的动机?这种状态还有其他优点吗?
和
2)看起来像object-keyed-by-id方法使得处理API的标准JSON输入/输出变得更加困难.(这就是我首先使用对象数组的原因.)因此,如果你采用这种方法,你是否只使用一个函数在JSON格式和状态形状格式之间来回转换它?这看起来很笨拙.(虽然如果你提倡这种方法,你的推理是否比上面的对象数组减少器更少笨重?)
和
3)我知道Dan Abramov设计的redux在理论上是状态数据结构不可知的(如"惯例"所示,顶级状态是一个对象或一些其他键值集合,如Map,但从技术上讲它可以是任何类型,"强调我的".但鉴于上述情况,是否只是"建议"将其保持为ID键入的对象,或者是否存在其他无法预料的痛点,我将通过使用一系列对象来解决这个问题,这样我就应该中止计划并尝试坚持使用ID键入的对象?
DDS*_*DDS 42
Q1:reducer的简单性是不必搜索数组以找到正确的条目.不必搜索阵列是有利的.选择器和其他数据访问器可以并且通常可以访问这些项目id.必须在阵列中搜索每次访问都会成为性能问题.当阵列变大时,性能问题会急剧恶化.此外,随着您的应用变得更加复杂,在更多地方显示和过滤数据,问题也会恶化.这种组合可能是有害的.通过访问项目id,访问时间从更改O(n)为O(1),对于大型n(此处为数组项目),这会产生巨大差异.
Q2:您可以normalizr用来帮助您进行从API到商店的转换.从normalizr V3.1.0开始,你可以使用denormalize来反过来.也就是说,应用程序通常比数据生产者更多的消费者,因此转换到商店通常更频繁地完成.
问题3:使用数组遇到的问题不是存储约定和/或不兼容问题,而是更多的性能问题.
Mar*_*olo 11
将应用程序的状态视为数据库.
这是关键的想法.
1)具有唯一ID的对象允许您在引用对象时始终使用该id,因此您必须在actions和reducers之间传递最小数量的数据.它比使用array.find(...)更有效.如果使用数组方法,则必须传递整个对象并且很快就会变得混乱,最终可能会在不同的reducers,actions或甚至容器中重新创建对象(您不希望这样).视图将始终能够获取完整对象,即使它们的关联reducer仅包含ID,因为在映射状态时,您将获得集合(视图获取整个状态以将其映射到属性).由于我所说的所有内容,操作最终只有最小量的参数,并且减少了最小的信息量,试一试,尝试这两种方法,你会发现架构最终更具可扩展性和清洁性如果集合具有ID,则为ID.
2)与API的连接不应影响存储和缩减器的体系结构,这就是为什么要采取措施来保持关注点的分离.只需将转换逻辑放入和放出API中的可重用模块,在使用API的操作中导入该模块,应该是它.
3)我使用带有ID的结构的数组,这是我所遭受的不可预见的后果:
我最终改变了我的数据结构并重写了很多代码.你已被警告过,请不要让自己陷入困境.
也:
4)大多数带ID的集合都是使用ID作为整个对象的引用,你应该利用它.API调用将获取ID ,然后获取其余参数,因此您的操作和减少器也将获得.
1)减速器的简单性是否采用对象键控id方法的动机?这种状态还有其他优点吗?
您希望将实体保存在以ID作为键存储的对象(也称为规范化)中的主要原因是,使用深层嵌套对象(这是您通常从更复杂的应用程序中的REST API获取的内容)非常麻烦-适用于您的组件和减速器.
使用当前示例来说明规范化状态的好处有点困难(因为您没有深层嵌套的结构).但是,让我们说选项(在您的示例中)也有一个标题,并由系统中的用户创建.这会使响应看起来像这样:
[{
id: 1,
name: 'View',
open: false,
options: [
{
id: 10,
title: 'Option 10',
created_by: {
id: 1,
username: 'thierry'
}
},
{
id: 11,
title: 'Option 11',
created_by: {
id: 2,
username: 'dennis'
}
},
...
],
selectedOption: ['10'],
parent: null,
},
...
]
Run Code Online (Sandbox Code Playgroud)
现在假设您要创建一个组件,该组件显示已创建选项的所有用户的列表.要做到这一点,首先必须请求所有项目,然后遍历每个选项,最后获取created_by.username.
更好的解决方案是将响应规范化为:
results: [1],
entities: {
filterItems: {
1: {
id: 1,
name: 'View',
open: false,
options: [10, 11],
selectedOption: [10],
parent: null
}
},
options: {
10: {
id: 10,
title: 'Option 10',
created_by: 1
},
11: {
id: 11,
title: 'Option 11',
created_by: 2
}
},
optionCreators: {
1: {
id: 1,
username: 'thierry',
},
2: {
id: 2,
username: 'dennis'
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用这种结构,列出已创建选项的所有用户(我们将它们隔离在entities.optionCreators中,因此我们只需循环遍历该列表)就更容易,也更有效.
显示例如已为ID为1的过滤器项创建选项的用户名也很简单:
entities
.filterItems[1].options
.map(id => entities.options[id])
.map(option => entities.optionCreators[option.created_by].username)
Run Code Online (Sandbox Code Playgroud)
2)看起来像object-keyed-by-id方法使得处理API的标准JSON输入/输出变得更加困难.(这就是我首先使用对象数组的原因.)因此,如果你采用这种方法,你是否只使用一个函数在JSON格式和状态形状格式之间来回转换它?这看起来很笨拙.(虽然如果你提倡这种方法,你的推理是否比上面的对象数组减少器更少笨重?)
可以使用例如normalizr来标准化JSON响应.
3)我知道Dan Abramov设计的redux在理论上是状态数据结构不可知的(如"惯例"所示,顶级状态是一个对象或一些其他键值集合,如Map,但从技术上讲它可以是任何类型,"强调我的".但鉴于上述情况,是否只是"建议"将其保持为ID键入的对象,或者是否存在其他无法预料的痛点,我将通过使用一系列对象来解决这个问题,这样我就应该中止计划并尝试坚持使用ID键入的对象?
这可能是对具有大量嵌套API响应的更复杂应用的推荐.但是在你的特定例子中,它并不重要.
| 归档时间: |
|
| 查看次数: |
23837 次 |
| 最近记录: |