简体   繁体   中英

Can't get state to update array inside of an object correctly in REACT/REDUX

I am going to break this down step by step for what I want to happen so hopefully people can understand what I am wanting.

Using React/Redux, Lodash

  1. I have many post that are sent from a back end api as an array. Each post has an _id . When I call on the action getAllPost() it gives me back that array with all the post. This is working just fine.

  2. I then dispatch type GET_ALL_POSTS and it triggers the reducer reducer_posts to change/update the state.

reducer:

export default function(state = {}, action) {
  switch(action.type) {
    case GET_ALL_POSTS:
    const postsState =  _.mapKeys(action.payload.data, '_id');
    //const newPostsState = _.map(postsState, post => {
      //const newComments = _.mapKeys(post.comments, '_id');
    //});
      return postsState;
    break;
    default:
      return state;
    break;
  }
}
  1. As you can see I change the array into one giant object that contains many post as objects with keys that are equal to their '_id'. This works just fine and returning this part of the state also works fine.
  2. As I mentioned each of these posts has a comments value that is an array. I would like to change the comments array into one large object that holds each comment as an object with a key that is equal to their '_id' just like I did in the post.
  3. Now I need to do this all at once and return the newly created state with One large object that contains all the post as objects and on each of those post there should be a comments object that contains all the comments as objects. I will try to write some example code to show what I am trying to do.

Example:

BigPostsObject { 
1: SinglePostObject{}, 
2: SinglePostObject{}, 
3: SinglePostObject {
  _id: '3',
  author: 'Mike',
  comments: BigCommentObject{1: SingleCommentObject{}, 2: SingleCommentObject{}}
 }
}

I hope that the example kind of clears up what I am trying to do. If it still is confusing as to what I am doing then please ask and also please do not say things like use an array instead. I know I can use an array, but that is not helpful to this post as if others want to do it this way that is not helpful information.

I believe nowadays JS builtin function can do this without requiring external libraries. Anyway this should be the way to go. I will really encourage you getting back to js builtin functions.

var data = [
 {
  _id: '3',
  title: 'Going on vaccation',
  comments:[ 
    {_id: 1, comment: 'hello'},
    {_id: 2, comment: 'world'}           
  ] 
 }, 

 {
  _id: '2',
  title: 'Going to dinner',
  comments:[ 
    {_id: 1, comment: 'hello'},
    {_id: 2, comment: 'world'}           
  ] 
 } 

]

//you can use JS builtin reduce for this
var transformedPost= _.reduce(data, function(posts, post) {
  var newPost = Object.assign({}, post)
  newPost._id=post._id
  //you can use js builtin map for this 
  newPost.comments = _.mapKeys(post.comments, '_id')

  // if you are using es6, replace the last three line with this 
  //return Object.assign({}, posts, {[newPost._id]: newPost})

  var item = {}
  item[newPost._id]=newPost
  return Object.assign({}, posts, item)
},{});

console.log(transformedPost)

https://jsbin.com/suzifudiya/edit?js,console

Write a function that processes all the comments from the comments array for each post you have in the posts array:

function processComment(post) {
   post.bigCommentsObject = _.mapKeys(post.comments, '_id');
   // now the comments array is no longer needed
   return _.omit(post, ['comments']);

}

Now use that function to turn each comments array into a big object with all the comments WHILE it still is in the array. Then afterwards turn the array itself in a big object:

const commentsProcessed =  _.map(action.payload.data, procesComment);
const postsState =  _.mapKeys(commentsProcessed, '_id');   

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