Redux规范化状态树:帖子和评论

4
Redux建议使用规范化的应用程序状态树,但我不确定在这种情况下是否是最佳实践。假设以下情况:
  1. 每个Circle有多个Posts
  2. 每个Post有多个Comments

在后端数据库中,每个模型如下所示:

Circle:

{
  _id: '1'
  title: 'BoyBand'
}

职位:

{
  _id: '1',
  circle_id: '1',
  body: "Some Post"
}

评论:

{
  _id: '1',
  post_id: '1',
  body: "Some Comment"
}

在前端应用程序状态(所有reducers的最终结果)中,其外观如下:

{
  circles: {
    byId: {
      1: {
        title: 'BoyBand'
      }
    },
    allIds: [1]
  },
  posts: {
    byId: {
      1: {
        circle_id: '1',
        body: 'Some Post'
      }
    },
    allIds: [1]
  },
  comments: {
    byId: {
      1: {
        post_id: '1',
        body: 'Some Comment'
      },
    allIds: [1]
  }
}

现在,当我进入CircleView页面时,我从后端获取Circle,其中包含与之相关的所有postscomments

export const fetchCircle = (title) => (dispatch, getState) => {
  dispatch({
    type: constants.REQUEST_CIRCLE,
    data: { title: title }
  })

  request
    .get(`${API_URL}/circles/${title}`)
    .end((err, res) => {
      if (err) {
        return
      }

      // When you fetch circle from the API, the API returns:
      // {
      //   circle: circleObj,
      //   posts: postsArr,
      //   comments: commentsArr
      // }
      // so it's easier for the reducers to consume the data

      dispatch({
        type: constants.RECEIVE_CIRCLE,
        data: (normalize(res.body.circle, schema.circle))
      })
      dispatch({
        type: 'RECEIVE_POSTS',
        data: (normalize(res.body.posts, schema.arrayOfPosts))
      })
      dispatch({
        type: 'RECEIVE_COMMENTS',
        data: (normalize(res.body.comments, schema.arrayOfComments))
      })
    })
}

到目前为止,我认为我以相当标准的方式完成了所有工作。但是,当我想要渲染每个Post组件时,我意识到与将帖子与其评论一起填充相比,这种方法变得低效(O(N^2))。保持状态树如下格式可以提高效率。

{
  circles: {
    byId: {
      1: {
        title: 'BoyBand'
      }
    },
    allIds: [1]
  },
  posts: {
    byId: {
      1: {
        circle_id: '1',
        body: 'Some Post'
        comments: [arrOfComments]
      }
    },
    allIds: [1]
  }
}

这与我对redux状态树的理解相悖,我认为在redux状态树中,最好保持所有内容都规范化。

问:实际上,在这种情况下,我应该保持内容非规范化吗?我如何确定该做什么?


你是担心性能问题,树的重建,还是其他方面? - mash
你能添加导致性能瓶颈的代码吗?组件和容器代码可能是原因吗? - Pierre Criulanscy
因为您的方法没有任何问题,您只是根据评论的ID选择评论正文,即使它是O(n ^ 2),其中n是帖子数量,这也不应该太麻烦。 - Pierre Criulanscy
2个回答

2
我会选择:是的,对其进行规范化,但请在后端完成!
为什么呢?
- 删除更容易
否则,每次想要删除一个圆圈或帖子时,您都必须追踪相关的帖子和评论。
- 处理数据更容易
否则,您将不得不一遍又一遍地对数据进行相同的变换,以便您可以选择与特定圆圈或帖子相关的数据集。
- 您没有任何多对多关系
您没有多个链接到同一评论的帖子,因此将数据规范化就是有意义的。
- 您不应该受到API的限制
如果这是第三方API,则使您的后端获取API并在那里规范化数据。您不应该受到API的限制,我不知道您访问哪些数据,但如果API不可用,则可以为用户保存DNS查找并提供缓存数据。如果您依赖API处于启动状态,则会引入单个故障点。
关于您的性能问题,如果您在后端进行规范化,则它们应该是微不足道的,并且您应该对其进行测量并将关键代码进行代码审查。

0
在我看来,评论列表是针对每篇文章具体的。用户不能将一个评论发布到多个帖子中。而且,评论与帖子紧密耦合并没有什么问题。更新/删除特定评论很容易(postId和commentId都存在)。删除帖子也很简单。同样适用于圈子。删除特定用户的所有评论稍微麻烦一些,但不会太难。我认为没有严格的规则、正确的方法等等,更多地取决于情况。KiSS ;)

在考虑如何在客户端组织评论时,我阅读了这篇文章,它介绍了类似情况的可能的数据库结构。https://docs.mongodb.com/ecosystem/use-cases/storing-comments/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接