如何处理 Redux reducer 中的 tree-shaped 个实体?
How to handle tree-shaped entities in Redux reducers?
我一直在思考如何实现一个 reducer,它的实体可以有相同类型的 children。
我们以reddit评论为例:每条评论可以有child条评论,可以有评论本身等。
为简化起见,评论是 {id, pageId, value, children}
类型的记录,pageId
是 reddit 页面。
如何围绕它来建模减速器?我正在考虑让 reducer 成为一个地图 -> 评论的 ID,您可以在其中使用 pageId
.
按页面过滤
问题是,例如,当我们想向嵌套的评论添加评论时:我们需要在地图的根目录上创建记录,然后将其 id 添加到 parent child仁属性。要显示所有评论,我们需要获取所有评论,过滤我们在顶部的评论(例如,将作为 orderedList 保留在页面缩减器中),然后迭代它们,从评论中获取 objects 当我们遇到 children 使用递归时。
有没有比这更好的方法或者它有缺陷?
您的商店(reducer)结构可能与您想要的视图模型(您作为道具传递给组件的视图模型)不同。您可以将所有评论保存在数组中,并通过高级 'smart' 组件上的 mapStateToProps 中的链接将它们映射到树。您将在 reducer 中获得简单的状态管理和一个方便的组件视图模型。
这个问题的官方解决方案是使用 normalizr 来保持你的状态:
{
comments: {
1: {
id: 1,
children: [2, 3]
},
2: {
id: 2,
children: []
},
3: {
id: 3,
children: [42]
},
...
}
}
你是对的,你需要 connect()
Comment
组件,这样每个组件都可以从 Redux 商店递归查询它感兴趣的 children
:
class Comment extends Component {
static propTypes = {
comment: PropTypes.object.isRequired,
childComments: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired
},
render() {
return (
<div>
{this.props.comment.text}
{this.props.childComments.map(child => <Comment key={child.id} comment={child} />)}
</div>
);
}
}
function mapStateToProps(state, ownProps) {
return {
childComments: ownProps.comment.children.map(id => state.comments[id])
};
}
Comment = connect(mapStateToProps)(Comment);
export default Comment;
我们认为这是一个很好的妥协。您将 comment
作为道具传递,但组件从商店中检索 childrenComments
。
我一直在思考如何实现一个 reducer,它的实体可以有相同类型的 children。
我们以reddit评论为例:每条评论可以有child条评论,可以有评论本身等。
为简化起见,评论是 {id, pageId, value, children}
类型的记录,pageId
是 reddit 页面。
如何围绕它来建模减速器?我正在考虑让 reducer 成为一个地图 -> 评论的 ID,您可以在其中使用 pageId
.
问题是,例如,当我们想向嵌套的评论添加评论时:我们需要在地图的根目录上创建记录,然后将其 id 添加到 parent child仁属性。要显示所有评论,我们需要获取所有评论,过滤我们在顶部的评论(例如,将作为 orderedList 保留在页面缩减器中),然后迭代它们,从评论中获取 objects 当我们遇到 children 使用递归时。
有没有比这更好的方法或者它有缺陷?
您的商店(reducer)结构可能与您想要的视图模型(您作为道具传递给组件的视图模型)不同。您可以将所有评论保存在数组中,并通过高级 'smart' 组件上的 mapStateToProps 中的链接将它们映射到树。您将在 reducer 中获得简单的状态管理和一个方便的组件视图模型。
这个问题的官方解决方案是使用 normalizr 来保持你的状态:
{
comments: {
1: {
id: 1,
children: [2, 3]
},
2: {
id: 2,
children: []
},
3: {
id: 3,
children: [42]
},
...
}
}
你是对的,你需要 connect()
Comment
组件,这样每个组件都可以从 Redux 商店递归查询它感兴趣的 children
:
class Comment extends Component {
static propTypes = {
comment: PropTypes.object.isRequired,
childComments: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired
},
render() {
return (
<div>
{this.props.comment.text}
{this.props.childComments.map(child => <Comment key={child.id} comment={child} />)}
</div>
);
}
}
function mapStateToProps(state, ownProps) {
return {
childComments: ownProps.comment.children.map(id => state.comments[id])
};
}
Comment = connect(mapStateToProps)(Comment);
export default Comment;
我们认为这是一个很好的妥协。您将 comment
作为道具传递,但组件从商店中检索 childrenComments
。