0

I have an initial state like so:

const initState = {
    posts: data
}

now posts is something like :

[
  {
    "id": "",
    "text": "",
    "slug": "",
    "title": "",
    "comments": []
  },

//some more here
]

So what I want to do is, when dispatch is fired I want to add new comments to that specific comments array. This is how I do it:

 if (action.type === "ADD_COMMENT") {
        let findPost = state.posts.find(post => post.slug === action.payload.comment.postSlug);
        let index = state.posts.indexOf(findPost);
        console.log(findPost);

        return {
            ...state,
            posts: [...state.posts,
            state.posts[index].comments = [action.payload.comment, ...state.posts[index].comments]]
        }
    }

Even though my app works completely fine I have a problem with the redux state. Because everytime action is happened it adds new comments in to that specific array along with a new array in to state.

So in case of firing new action I do get something like this:

[
  {
    "id": "",
    "text": "",
    "slug": "",
    "title": "",
    "comments": ["comment here"]
  },
[
  {
    "comments": ["comment here"]
  },

//some more here
]

]

In each click it creates a new entry in to my state which I don't want at all. How can I make it possible that it only adds the comments in to that specific array but not as separate entry?

2
  • how do you dispatch the add comment event? Commented Jun 2, 2020 at 13:30
  • instead of using find and indexOf, you can pass the index of the item in your dispatcher. Commented Jun 2, 2020 at 13:31

2 Answers 2

2

You push the new comment in the "posts" array instead of the post's object.

You can try with a map

if (action.type === "ADD_COMMENT") {

 const posts = state.posts.map(post => {
       if( post.slug === action.payload.comment.postSlug){
          post.comments.unshift(action.payload.comment);
       }
       return post
    });

    return {...state, posts}
}

EDIT : With this solution you mutate the state, wich is not recommended To avoid this simply copy your posts in a new variable

let posts = [...state.posts]

And then do your map.

Sign up to request clarification or add additional context in comments.

4 Comments

elegant way to handle that problem
Definitely brilliant. Thanks a lot.
but this mutates the state. see stackoverflow.com/questions/37755997/…
There's no point of doing return {...state, posts} since you are directly changing state.
2

Pass the index of comments array in your payload.

if (action.type === 'ADD_COMMENT') {
  // get the index of the item from the payload
  const index = action.payload.index;
  // create a copy
  const posts = [...state.posts];
  // add comment to comments array
  posts[index].comments.push(action.payload.comment);

  console.log(posts[index]);

  return {
    ...state,
    posts: posts,
  };
}

1 Comment

That's even better solution. Thank you for your time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.