javascript 如何在 Redux reducer 中处理树形实体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32798193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 15:46:47  来源:igfitidea点击:

How to handle tree-shaped entities in Redux reducers?

javascriptreactjs-fluxfluxredux

提问by Vincent P

I'm a bit stuck thinking on how to implement a reducer where its entities can have children of the same type.

我在思考如何实现一个减速器时,它的实体可以有相同类型的子级,我有点犹豫。

Let's take reddit comments as an example: each comment can have child comments that can have comments themselves etc. For simplification reason, a comment is a record of type {id, pageId, value, children}, with pageIdbeing the reddit page.

让我们reddit的评论为例:每个注释可以有,可以有自己的意见等。为了简化的原因孩子的意见,评论是一种记录{id, pageId, value, children},以pageId作为reddit的页面。

How would one model the reducer around that? I was thinking of having the reducer be a map -> id of the comments where you can filter by page using the pageId.

一个人将如何围绕这个建模减速器?我在考虑让 reducer 成为地图 -> 评论的 id,您可以在其中使用pageId.

The issue is that for example when we want to add a comment to a nested one: we need to create the record on the root of the map and then add its id in the parent children property. To display all the comments we'd need to get all of them, filter those that we have at the top (that would be kept in the page reducers as an orderedList for example) and then iterate on them, fetching from the comments objects when we encounter children using recursion.

问题是,例如,当我们想向嵌套的注释添加注释时:我们需要在地图的根目录上创建记录,然后将其 id 添加到父子级属性中。要显示我们需要获取所有评论的所有评论,请过滤我们在顶部拥有的评论(例如,将作为orderedList 保存在页面减速器中),然后对它们进行迭代,在出现时从评论对象中获取我们遇到了使用递归的孩子。

Is there a better approach than that or is it flawed?

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

回答by Dan Abramov

The official solution to this is to use normalizrto keep your state like this:

官方对此的解决方案是使用normalizr来保持您的状态,如下所示:

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

You're right that you'd need to connect()the Commentcomponent so each can recursively query the childrenit's interested in from the Redux store:

你说你需要正确connect()Comment组件,这样每个人都可以递归查询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;

We think this is a good compromise. You pass commentas a prop, but component retrieves childrenCommentsfrom the store.

我们认为这是一个很好的妥协。您comment作为道具传递,但组件childrenComments从商店中检索。

回答by Victor Suzdalev

Your store (reducer) structure could differ from your desired view model (one you pass as props to components). You could just keep all comments in array and map them to a tree by links in mapStateToProps on high-level 'smart' component. You'll get simple state management in reducer and a handy view model for components to work with.

您的存储(reducer)结构可能与您想要的视图模型(您作为组件的道具传递的模型)不同。您可以将所有评论保留在数组中,并通过高级“智能”组件上的 mapStateToProps 中的链接将它们映射到树。您将在 reducer 中获得简单的状态管理和一个方便的组件视图模型。