简体   繁体   中英

How to store and update deeply nested structures in ImmutableJS

I am building little blog with react+redux and I cant figure out how should I go about replying to comments under blog post. I am getting comments structure for one blog post which looks something like this.

"[
{"_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":[]
  }
]},
{...}
]

How do I store it in ImmutableJS state so I can easily add replies to comments based on their _id ? Also the comments have to be iterable because Im rendering them into comment tree afterwards but I dont think that should be a problem as long as ImmutableJS data structures are used. Basically I dont know how I should implement this function in my reducer.

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

EDIT

Here is jsbin showing what I am trying to achieve. I just want to be able to reply to comments that's all

You gotta break this down a bit.

So firstly let's add the comments to an Immutable.Map

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

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

You now have an Immutable.List under coolPostId , so you then want to update that list by push ing a new comment:

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

That'll pass your first test:

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

The second part is just as easy but you need to map cover your comments and check if the _id matches your metadata.

Here's your setup:

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

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

The next line depends on a function that will do the _id check,

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

And the final bit of the puzzle is the addReply predicate:

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

Here is a full jsbin for review

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM