【问题标题】:How to store and update deeply nested structures in ImmutableJS如何在 ImmutableJS 中存储和更新深度嵌套的结构
【发布时间】:2016-02-03 17:13:42
【问题描述】:

我正在用 react+redux 构建一个小博客,我不知道我应该如何在博客文章下回复 cmets。 我正在为一篇看起来像这样的博客文章获取 cmets 结构。

"[
{"_id":"5676ed8b9104691f3b85b687",
"content":"Lorem",
"creator":"Admin",
"replies":[
  {
    "_id":"5676ede4b7a9044c3c1d9641",
    "content":"Ipsum",
    "creator":"Admin",
    "replies":[
      {
        "_id":"5676eec224ab8fe23c7ce4c6",
        "content":"Dolor",
        "creator":"Admin",
        "replies":[]
      },
      {
        "_id":"5676eeda1c0e3d093d1f90a0",
        "content":"Sit",
        "creator":"Admin",
        "replies":[]
      }
    ]
  },
  {
    "_id":"5676ee5b4b03bbac3c1f7544",
    "content":"Amet",
    "creator":"Admin",
    "replies":[]
  },
  {
    "_id":"5676ee91c43c05c63c319ace",
    "content":"Sup",
    "creator":"Admin",
    "replies":[]
  }
]},
{...}
]

如何将它存储在 ImmutableJS 状态,以便我可以轻松地根据他们的 _id 添加回复到 cmets?此外,cmets 必须是可迭代的,因为我之后会将它们渲染到评论树中,但我认为只要使用 ImmutableJS 数据结构,这应该不是问题。基本上我不知道我应该如何在我的减速器中实现这个功能。

[REPLY_COMMENT]: (state, { payload }) => {
  const { _id, comment } = payload
  let newState = ???
  return newState
}

编辑

这里是jsbin,展示了我想要实现的目标。我只是希望能够回复cmets而已

【问题讨论】:

  • 我不太明白您的问题,您可以使用Immutable.fromJS 方法将上面的可变Array 与嵌套的Objects 转换。你问的是这个吗?这将生成一个Immutable.List,其中Immutable.Map 作为评论项的数据类型。
  • 我添加了jsbin,请看一下。我知道我可以使用Immutable.fromJS,但是如何将数据添加到特定的评论回复中呢?想象一下,您正在博客下构建 cmets 部分,您会选择什么方法和ImmutableJS 数据结构?

标签: javascript reactjs immutability redux immutable.js


【解决方案1】:

你得把它分解一下。

首先让我们将 cmets 添加到 Immutable.Map

state = state.update('coolPostId', post => Immutable.fromJS(comments));

const replyToPostComment = {
  _id: '1234',
  content: 'Hello',
  creator: 'RandomUser',
  replies: []
};

您现在在coolPostId 下有一个Immutable.List,因此您想通过push 发送新评论来update 该列表:

state = state.update('coolPostId', comment => comment.push(Immutable.fromJS(replyToPostComment)));

这将通过你的第一个测试:

const expected = state.get('coolPostId').last();
expect(expected.toJS()).to.deep.equal(replyToPostComment);

第二部分同样简单,但您需要映射您的 cmets 并检查 _id 是否与您的元数据匹配。

这是你的设置:

const replyComment = {
  _id: '5678',
  content: 'Wellcome',
  creator: 'RandomUser2',
  replies: []
};

const reply = {
  postId: 'coolPostId',
  commentId: '1234',
  comment: replyComment
};

下一行取决于执行_id 检查的函数,

state = state.get(reply.postId)
  .map(comment => addReply(comment)(reply));

谜题的最后一点是addReply 谓词:

const addReply = c => cr => c.get('_id') === cr.commentId ? c
  .update('replies', replies => replies.push(Immutable.fromJS(cr.comment)) ) : c;

这是一个完整的jsbin 供审核

【讨论】:

  • 谢谢,但我不确定这是否适用于深度嵌套的评论回复?就像评论是否有回复并且该回复有更多回复等等。我要回复的 postId+commentId 对可以在评论树的深处。
  • 您可以将addReply 替换为comment.updateIn,请参阅文档。
  • 你能用updateIn 编辑你的例子吗?我无法让它工作,从你的回复来看,这似乎很容易解决。我显然错过了一些东西。
  • 您能否更新您的 jsbin 中的模型以显示回复的回复的回复... 看起来像,因为它并不完全清楚。回复和回复评论之间的键不匹配,我不确定它在树下的一个级别时会是什么样子?在您上面概述的场景中,您如何知道父母是什么?
  • 评论可以在其replies 属性中包含另一个cmets。只有一个模型。回复是另一条评论replies 属性中的评论。像树形结构,一个节点可以有多个子节点等等。而且我认为我的示例中的键很有意义我用_id: '1234'添加了根评论并用_id: '5678'回复它
猜你喜欢
  • 2019-02-03
  • 2014-06-19
  • 1970-01-01
  • 2021-06-25
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多