如何处理Flux中的关系?

Aro*_*ost 12 javascript flux reactjs reactjs-flux

想象一下像Quora这样的东西.

[
  {
    type: "question",
    answers: [
      {
        type: "answer",
        upvotes: [
          {
            type: "upvote"
          }
          /* more upvotes */
        ],
        comments [
          {
            type: "comment"
          }
          /* more comments */
        ]
      }
      /* more answers */
    ]
  }
  /* more questions */
]
Run Code Online (Sandbox Code Playgroud)

我肯定会有类似的东西QuestionsStore.但对于所有儿童实体,我不确定如何处理它们.来自Backbone我认为每个答案应该有一个UpvotesStore和一个CommentsStore组件将从这些商店获取他们的数据并订阅他们的更新.据我所知,Flux,"儿童"/关系商店有点不常见.

当每个组件订阅更新时QuestionsStore,会导致类似:

/* in CommentsComponent */
onUpdate: function() {
  this.setState({
    comments: QuestionsStore.getComments({questionId: 1, answerId: 1});
  });
}
Run Code Online (Sandbox Code Playgroud)

或更极端:

/* in CommentComponent */
onUpdate: function() {
  this.setState(QuestionsStore.getComment({questionId: 1, answerId: 1, commentId: 1}));
}
Run Code Online (Sandbox Code Playgroud)

由于关系数据存在于树结构中,因此每个组件都需要知道所有"父"id,以便能够从中查询其数据QuestionsStore.我发现这有些奇怪.

那么处理关系(一对多)数据结构的最佳Flux模式是什么?

Ada*_*one 2

我看到的两个主要选项是保留嵌套结构,或者将其解析为平面结构,其中每个对象根据其关系包含对其他对象的引用。我认为最好的方法取决于需要如何访问数据。

嵌套结构

如果它始终反映您的视图层次结构,则保持嵌套结构会使事情相对容易。例如,考虑:

// render a <Question/>
render: function() {
  var question = this.props.data,
      answers = question.answers.map(function(answer, i) {
        return <Answer key={i} data={answer}/>
      });

  return (
    <div className="question">
      {answers}
    </div>
  );
}

// render an <Answer/>
render: function() {
  var answer = this.props.data,
      comments = answer.comments.map(function(comment, i) {
        return <Comment key={i} data={comment}/>
      });

  return (
    <div className="answer">
      ...
      {comments}
    </div>
  );
}

// and so on
Run Code Online (Sandbox Code Playgroud)

让顶级组件从 Store 获取数据并通过 props 传递数据,这样比让每个组件跟踪索引以在 Store 中查找嵌套数据更容易管理。

这种方法的潜在缺点是嵌套数据更难从其上下文外部访问。例如,如果您想跟踪给定用户的所有评论,您的用户数据仍然必须借助索引来跟踪哪些问题、每个问题的哪些答案索引以及每个答案的哪些评论索引指向正确的评论。在这种情况下,您可能会受益于扁平数据结构。

扁平结构

扁平结构需要更多的工作来设置,但具有每个对象都可以立即访问的优点。假设您的数据作为嵌套对象出现,则需要通过遍历树来查找所有节点来解析数据,为每个节点提供唯一的键,用对适当键的引用替换其子树,然后将所有结果存储在合适的商店。但正如 Dan Abramov 指出的那样,有人已经提供了一个模块来促进这一点。

现在,您的问题可以引用答案,每个答案都可以引用评论,从而可以轻松地重新创建原始嵌套结构;但您的用户也可以参考评论,而无需跟踪它们与答案或问题的关系。

这基本上就是 Git 内部的工作方式;它对于包含大量冗余的数据树特别有效(例如,包含未更改文件的多个提交都可以指向同一个对象)。