关于normalizing state shape的每个文档,本质上列表的数据将由Id作为对象存储在状态树中,这意味着从API调用返回的数组数据首先要转换为动作创建者中的对象。然后,必须将对象数据转换回mapStateToProps()中的数组,以便使用render()中的数组的.map()函数呈现结果道具。这种来回转换是否是标准状态的合理成本?或者使用ReactJS和Redux处理列表数据是否有更好的设计模式?
答案 0 :(得分:4)
是的,您所描述的是如果存储规范化状态然后希望组件使用数组,则必须执行的操作。
通常,我的州将是这样的:
users: {
byId: {
// map of objects keyed by id
},
ids: [//array of ids],
}
请注意,我要保持ID以跟踪从服务器返回项目的顺序;取决于用例,可能需要也可能不需要。如果顺序不重要,您可能只能存储对象并使用Object.keys(可能是因为您最终按其他条件排序)。
通常,数据的最易消费形式是数组,因此您需要定义一个选择器来获取用户。遵循colocating reducers and selectors的模式,您将拥有
// User reducer
export const getUsers = (state) => state.ids.map(id => state.byId[id])
和
// Root reducer
import users, * as fromUsersReducer from './users
const reducer = combineReducers({
users,
})
export const getUsers = (state) => fromUsersReducer(state.users)
然后是你的容器
import { connect } from 'react-redux'
import { getUsers } from 'reducers/root'
import UsersComp from './users
const mapStateToProps = (state) => ({
users: getUsers(state),
})
export default connect(mapStateToProps)(UsersComp)
就转换是否合理而言,取决于用例。标准化状态变得非常重要的地方在于您可以编辑数据,或者您的数据与其他数据相关(从用户获取所有帖子等)。但是,如果您所做的只是获取数据列表,而您只是显示该列表,则可能不需要进行规范化。
如果您最终需要为数据添加更复杂的操作,则可以轻松切换,假设您严格仅通过选择器访问状态。归一化数据通常被视为最佳实践,因为您通常最终会使用数据执行更复杂的操作,其中具有标准化形状是有利的。但这不是一个硬性规则或任何事情;有些情况下肯定不需要它。
您在这里看到的唯一实际成本是
您可以使用reselect轻松降低效果。这通常不是必需的。就额外的代码而言,它基本上是一遍又一遍的相同类型的东西,所以它很容易抽象,而且代码本身实际上并不复杂。如果所有内容都存储为数组,那么复杂应用程序中的reducer / selector代码就会复杂得多。