如何处理 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