I am receiving a list of comments from a graphql backend in the following format:
[
{
"__typename": "Comment",
"id": "1",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "test 1"
},
{
"__typename": "Comment",
"id": "2",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "this is a comment"
},
{
"__typename": "Comment",
"id": "34",
"userId": "1",
"postId": "1",
"parentCommentId": "1",
"content": "reply to test1"
},
{
"__typename": "Comment",
"id": "35",
"userId": "1",
"postId": "1",
"parentCommentId": "34",
"content": "nested reply to "reply to test1"nn"
},
{
"__typename": "Comment",
"id": "36",
"userId": "1",
"postId": "1",
"parentCommentId": "34",
"content": "test?"
}
]
The comments with parentCommentId === null
are the highest level comments, while comments where parentCommentId !== null
are replies to a comment where id === parentCommentId
I would like to transform this data structure to something like:
[{
"__typename": "Comment",
"id": "1",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "test1",
"replies": [{
"__typename": "Comment",
"id": "34",
"userId": "1",
"postId": "1",
"parentCommentId": "1",
"content": "reply to test1",
"replies": [{
"__typename": "Comment",
"id": "35",
"userId": "1",
"postId": "1",
"parentCommentId": "34",
"content": "reply to test1"
}]
}]
},
{
"__typename": "Comment",
"id": "2",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "this is a comment",
"replies": []
}
]
I have the following function to do the data transformation:
function formatData(comments: Array < IComment > ) {
let commentList = Array < IComment > ();
// add comments without `parentCommentId` to the list.
// these are top level comments.
for (let i = 0; i < comments.length; i++) {
if (!comments[i].parentCommentId) {
commentList.push({ ...comments[i],
replies: []
});
}
}
for (let i = 0; i < comments.length; i++) {
if (comments[i].parentCommentId) {
const reply = comments[i];
mapReplyToComment(commentList, reply);
}
}
return commentList;
function mapReplyToComment(
commentList: Array < IComment > ,
reply: IComment
): any {
return commentList.map((comment) => {
if (!comment.replies) {
comment = { ...comment,
replies: []
};
}
if (comment.id === reply.parentCommentId) {
comment.replies.push(reply);
return comment;
} else {
return mapReplyToComment(comment.replies, reply);
}
});
}
}
However this only works for one level deep into the object tree. so I am getting the replies of a main comment, but replies to replies are not added to the object.
this is what I am getting now:
[{
"__typename": "Comment",
"id": "1",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "test1",
"replies": [{
"__typename": "Comment",
"id": "34",
"userId": "1",
"postId": "1",
"parentCommentId": "1",
"content": "reply to test1"
// -- I should have here another node of "replies"
}]
},
{
"__typename": "Comment",
"id": "2",
"userId": "1",
"postId": "1",
"parentCommentId": null,
"content": "this is a comment",
"replies": []
}
]
Could you please point out what am I doing wrong and provide some explanation?
Thanks in advance