假设以下情况:
1. Page has many posts
2. Post has many comments
我有以下减速器:
1. PagesReducer
2. PostsReducer
3. PostReducer
4. CommentsReducer
我现在有以下状态:
pagesByTitle: {
dorrisPage: {
isFetching: false,
data: {
_id: "..."
title: "dorrisPage",
},
posts: [
{
isFetching: false,
data: {
_id: "..",
body: ".."
},
comments: [..]
}
]
}
}
上面的结构最初看起来还不错,但我意识到我必须传递action
的子状态。例如,如果我调度了一个名为
ADD_COMMENT
我会将操作传递给PagesReducer
,PostsReducer
,PostReducer
和CommentsReducer
,最后CommentsReducer
将处理该操作。我想这是在我意识到为什么在Redux中推荐规范化状态的时候。
你能帮我解决以下问题吗?
答案 0 :(得分:1)
你应该避免嵌套。
来自redux docs:
在更复杂的应用中,您将需要不同的实体 互相参考。我们建议您保持自己的状态 尽可能标准化,没有任何嵌套。保持每个实体 以ID作为键存储的对象,并使用ID从中引用它 其他实体或列表。将应用程序的状态视为数据库。这个 方法在normalizr的文档中有详细描述。
对于标准化状态,您可以使用normalizr
pages:{
items:{
1:{id: 1,title: "dorrisPage", posts:[33,57]}
2:{id: 2, title: "anotherPage",posts:[57]}
},
isFetching: false,
itemIds:[1,2,..]
},
posts:{
items:{
33:{id: 33,title: "Post33", comments:[1,2]}
57:{id: 57, title: "Post57", comments:[]}
},
isFetching: false,
itemIds:[33,57,..]
}
comments:{
items:{
1:{id: 1, user: "user1", text:"fds"}
2:{id: 2, user: "user2", text:"fds2"}
},
isFetching: false,
itemIds:[1,2,..]
}
<强>&#34; itemIds&#34;物品订购是必要的
然后减速器可能看起来像这样
export const posts = (state = initialState, action) => {
switch (action.type) {
case type.FETCH_POSTS_REQUEST:
case type.FETCH_POSTS_FAILURE:
return {...state, isFetching: action.isFetching};
case type.FETCH_POSTS_SUCCESS:
return {...state,
isFetching: action.isFetching,
items: action.entities.posts, itemsIds: action.result
};
case type.DELETE_POST:
return {...state,
items: omit(state.items, action.id),
itemsIds: state.itemsIds.filter(id=>id !== action.id)
};
case type.UPDATE_POST:
return {...state, items: {...state.items,
[action.post.id]: {...state.items[action.post.id],...action.post}}};
default:
return state;
}
}
通过ID更轻松地查询帖子:
const mapStateToProps = (state,ownProps) =({
post:state.posts.items[ownProps.id]
})
用于计算来自redux商店的派生数据,您可以使用Reselect创建已记忆的,可组合的选择器函数