如何处理Redux Reducer中的树形实体?

时间:2015-09-26 14:22:54

标签: javascript reactjs-flux flux redux

我有点想到如何实现一个reducer,其实体可以有相同类型的子节点。

我们以reddit评论为例:每条评论都可以有儿童评论,可以自己评论等。 出于简化原因,评论是{id, pageId, value, children}类型的记录,pageId是红色页面。

如何对减速机进行建模?我在想减速器是地图 - >您可以使用pageId按页面过滤的评论ID。

问题在于,例如当我们想要为嵌套的注释添加注释时:我们需要在地图的根上创建记录,然后在父子属性中添加其id。要显示我们需要获取所有这些注释的所有注释,请过滤掉我们在顶部的那些注释(例如,将它们作为orderedList保存在页面reducer中)然后迭代它们,从注释对象获取时我们遇到使用递归的孩子。

有没有比这更好的方法或有缺陷?

2 个答案:

答案 0 :(得分:36)

对此的官方解决方案是使用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

答案 1 :(得分:1)

您的商店(缩减器)结构可能与您想要的视图模型不同(您将其作为道具传递给组件)。您可以将所有注释保留在数组中,并通过mapStateToProps中的链接将它们映射到树中,这些链接位于高级&#39; smart&#39;零件。您将在reducer中获得简单的状态管理,并为要使用的组件提供便捷的视图模型。