我正在开发一个React网络应用。到目前为止,我总是将数据存储在如下数组中:
areas: [
{ id: 0, title: 'Some title', isSelected: false }
]
然后我就可以了
this.state.areas.map(x => <Component key={x.id} ... />
然而,在浏览Redux文档之后,我发现存储数据的优点如下:
areas: {
'some title': { id: 0, isSelected: false }
}
通过执行
,可以非常轻松地更新当前选定的区域this.state.areas['some title].isSelected = true
与通过id执行.filter相反,然后更新isSelected
。
但是,使用对象键而不是数组进行存储意味着我必须写:
{
Object.entries(this.props.areas).map(([k, v]) => {
return <Component key={k.id} ... />
})
}
可读性差得多,打字也多。
所以我的问题是:
Object.entries...
更好的方式来实现我的目标?或者有更好的方法吗?感谢。
答案 0 :(得分:4)
从您的问题来看,似乎您在将数组和值中的值存储为处于反应状态的对象时感到困惑。这取决于您的要求。
存储在数组中,如果数据仅用于显示目的而不会使用任何事件进行更改。比如,在选择框中渲染动态选项。您可以将值存储为数组,并可以使用“Array.map”创建组件数组并进行渲染。
当您更改事件的数据/更新数据时,通常会使用对象。在更新其中的特定值时,对象很方便。比如,您在第一列中使用复选框呈现表格行,而在复选框标记/取消标记上则需要更新相关的行数据属性。
如果您的应用程序需要完成两件事,您应该执行以下操作,
{
areas: ['areaid_0', 'areaid_1', 'areaid_2'],
areaDetails: {
'areaid_0': {title: 'Some title', isSelected: false},
'areaid_1': {title: 'Some title', isSelected: false},
'areaid_2': {title: 'Some title', isSelected: false}
}
}
谈到渲染,你可以这样做,
this.state.areas.map(x => {
const areaDetail = this.state.areaDetails[x];
<Component key={x} {...areaDetail}... />
})
当您想要更新任何对象时,您可以这样做,
this.state.areaDetails[x].isSelected = true;
希望,这对你有所帮助。
答案 1 :(得分:4)
将对象存储在某种“ID地图”中,这通常是recommended by the Redux docs。请注意,按照惯例,键是ID
,而不是像title
这样的任意属性。
虽然您确实可以使用已演示的Object.entries
样式,但您几乎总是希望拥有某种逻辑排序顺序。
您不应该依赖JavaScript保留键的排序顺序,因此,normalizr(Abramov推荐)等自动转换为此规范化结构的库也将返回result
数组将保留排序顺序的ID。 Reference Here
Redux的“规范化状态形状”文档还明确建议您依赖一系列ID来排序:
- 任何对单个项目的引用都应该通过存储项目的ID来完成。
- 应使用ID数组来表示排序。
您的状态可能如下所示:
{
areas: {1: {id: 1, title: 'some title'}, 2: {id: 2, title: 'other title'}},
areaIds: [1, 2],
}
然后你会像这样迭代:
areaIds.map(id => <Component key={id} area={areas[id]} />)
如果您真的想要Object.entries
方式,可以使用像lodash
这样的库,它可以让您轻松完成:
_.map(areas, area => <Component key={area.id} area={area} />)