2015-09-26 78 views
18

我有点卡住思考如何实现reducer它的实体可以有相同类型的孩子。如何在Redux reducer中处理树形实体?

让我们以reddit注释为例:每个注释可以包含可以自己评论的子注释等。 为了简化起见,注释是{id,pageId,value,children}类型的记录,其中pageId为reddit页面。

如何模拟减速机?我正在考虑使reducer成为地图 - >您可以使用pageId按页过滤的注释ID。

问题是,例如,当我们想要添加一个评论到一个嵌套的:我们需要在地图的根上创建记录,然后将其ID添加到父子物业中。要显示所有评论我们需要得到所有这些信息,过滤顶部顶部的那些信息(例如,将其作为有序列表保存在页面缩减器中),然后对它们进行迭代,当我们遇到使用儿童的时候从评论对象中获取递归。

有没有比这更好的方法,还是有缺陷?

+0

我认为你可以尝试normalizr:https://github.com/gaearon/normalizr自己没有使用它,所以我不知道它是否会帮助你在你的情况。 – Simon

+0

我知道normalizr,我更想知道是否有一个“接受”的解决方案,如何在组件中处理它。 除非你连接()每一条评论,否则每次更改都需要对normalizr做相反的处理,即使你连接的时候看起来有点像一团糟 –

回答

32

这个官方的解决方案是使用normalizr保持你的状态是这样的:

{ 
    comments: { 
    1: { 
     id: 1, 
     children: [2, 3] 
    }, 
    2: { 
     id: 2, 
     children: [] 
    }, 
    3: { 
     id: 3, 
     children: [42] 
    }, 
    ... 
    } 
} 

你说得对,你需要connect()Comment组件,这样每个人都可以递归查询children它的兴趣从Redux商店:

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

+0

但是你怎么用Schema做到这一点?请你举个例子 – alexrogins

+0

这个例子使用normalizr:https://github.com/reactjs/redux/tree/master/examples/real-world。此外normalizr有测试,希望应该展示如何使用它。 –

+0

如果你的数据不是来自一个API呢?我应该像normalizr那样建模我的数据吗? – Dave

1

您的商店(减速机)结构可能与您所需的视图模型不同(您将其作为道具传递给组件)。您可以将所有注释保留在数组中,并通过高级'智能'组件上的mapStateToProps中的链接将它们映射到树。您将在Reducer中获得简单的状态管理,并为组件使用提供便捷的视图模型。