Home > database >  Pushing object into an array which is a property of an object
Pushing object into an array which is a property of an object

Time:11-01

I'm trying to push objects to an array("replies") present inside an object(newProjObj.comments).

And while logging the entire object(newProjObj.comments), I get an empty array as the value of the property(newProjObj.comments.replies: [])

But while logging that specific property(console.log(newProjObj.comments.replies)), I get the desired output([{...},{...}])

export function structureCommentsWithReplies(projectDetails) {
    console.log(projectDetails)
    let newProjObj = {...projectDetails};
    console.log(newProjObj)
    // Filtering the actual comments
    let commsOnPost = newProjObj.comments.filter((comment) => comment.onPost);
    // Filtering replies to the comments above
    let commsOnComm = newProjObj.comments.filter((comment) => !comment.onPost);
    // Looping to the actual comments
    for(let [index, comment] of commsOnPost.entries()) {
        // Created a property "replies" for every comment initialised to []
        commsOnPost[index]["replies"] = []
        // Looping through filtered replies
        for(let reply of commsOnComm) {
            if((!reply.onPost) && (reply.commentOnID === comment.id)) {
                // Push the reply into "replies" property of appropriate actual comment
                commsOnPost[index]["replies"].push(reply) 
                console.log(commsOnPost[index]['replies']) // Logs the pushed reply as expected => [{ id:17, onPost:false, ... }]
                console.log(commsOnPost[index]) // Logs the comment object with replies property as EMPTY ARRAY => { id: 1, onPost: true, replies: [], ... }
            }
        }
    }
    newProjObj.comments = commsOnPost;
    console.log(newProjObj.comments[0]) // Logs the comment object with replies property as EMPTY ARRAY => { id: 1, onPost: true, replies: [], ... }
    console.log(newProjObj.comments[0].replies) // Logs the pushed reply as expected => [{ id:17, onPost:false, ... }]
    return newProjObj;
}

And the object being returned at the end also has an empty array as the value of the "replies" property.

I've written comments explaining each line as well if that helps.

Thank you!

CodePudding user response:

If I understand correctly, then you have an object (something) like this:

const projectDetails = {
  comments: [
    {
      id: 1,
      onPost: true,
    },
    {
      id: 2,
      onPost: false,
      commentOnID: 1,
    },
    {
      id: 3,
      onPost: false,
      commentOnID: 1,
    },
    {
      id: 4,
      onPost: true,
    },
    {
      id: 5,
      onPost: false,
      commentOnID: 4,
    },
  ]
}

and you would like to get something like this:

const newProjObj = {
  comments: [
    {
      id: 1,
      onPost: true,
      replies: [
        {
          id: 2,
          onPost: false,
          commentOnID: 1,
        },
        {
          id: 3,
          onPost: false,
          commentOnID: 1,
        },
      ],
    },
    {
      id: 4,
      onPost: true,
      replies: [
        {
          id: 5,
          onPost: false,
          commentOnID: 4,
        },
      ],
    },
  ]
}

If this is correct, then the following snippet would work:

const projectDetails = {
  comments: [{
      id: 1,
      onPost: true,
    },
    {
      id: 2,
      onPost: false,
      commentOnID: 1,
    },
    {
      id: 3,
      onPost: false,
      commentOnID: 1,
    },
    {
      id: 4,
      onPost: true,
    },
    {
      id: 5,
      onPost: false,
      commentOnID: 4,
    },
  ]
}

// only taking out the value that we'll be working with
const structureCommentsWithReplies = ({ comments, ...details }) => {

  // classifying items - in one pass &
  // retrieving the two objects we need
  const { commsOnPost, commsOnComm } = comments.reduce(
    (a, { onPost, ...rest }) => {
      if (onPost) {
        a.commsOnPost[rest.id] = {
          onPost,
          replies: [],
          ...rest
        }
      } else {
        a.commsOnComm = [...a.commsOnComm, {
          onPost,
          ...rest
        }]
      }
      return a
    }, {
      commsOnPost: {},
      commsOnComm: []
    })

  // adding items to their parent comments'
  // replies array
  commsOnComm.forEach(({ commentOnID, ...rest }) => {
    commsOnPost[commentOnID].replies = [
      ...commsOnPost[commentOnID].replies,
      { commentOnID, ...rest }
    ]
  })

  // returning the object with updated
  // comments section
  return {
    ...details,
    comments: Object.values(commsOnPost)
  }
}

const structured = structureCommentsWithReplies(projectDetails)
console.log('structured', structured)
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

This problem is coming the state updating. If you want to access it after update, use useEffect and attach the new posts to a state so you can add it to the dependencies array. If you want to run something directly, just use the new variable itself

  • Related