skip to Main Content

I have a react n-level app where the delete function is a recursive function utilizing Array.prototype.filter(). The data is an array of objects and in each object there can be an array that contains more data.

Data:

[
    {
        "id": 1,
        "hasParent": false,
        "hasChildren": true,
        "parentId": 0,
        "childrenIds": [
            3,
            5
        ],
        "text": "Opportunities don't happen, you create them.",
        "childComments": [
            {
                "id": 3,
                "hasParent": true,
                "hasChildren": true,
                "parentId": 1,
                "childrenIds": [
                    4
                ],
                "text": "one",
                "childComments": [
                    {
                        "id": 4,
                        "hasParent": true,
                        "hasChildren": false,
                        "parentId": 3,
                        "childrenIds": [],
                        "text": "two",
                        "childComments": []
                    }
                ]
            },
            {
                "id": 5,
                "hasParent": true,
                "hasChildren": false,
                "parentId": 1,
                "childrenIds": [],
                "text": "one",
                "childComments": []
            }
        ]
    },
    {
        "id": 2,
        "hasParent": false,
        "hasChildren": false,
        "parentId": 0,
        "childrenIds": [],
        "text": "Just one small positive thought in the morning can change your whole day.",
        "childComments": []
    },
    {
        "id": 6,
        "hasParent": false,
        "hasChildren": false,
        "parentId": 0,
        "childrenIds": [],
        "text": "More data one",
        "childComments": []
    },
    {
        "id": 7,
        "hasParent": false,
        "hasChildren": true,
        "parentId": 0,
        "childrenIds": [
            8
        ],
        "text": "More data two",
        "childComments": [
            {
                "id": 8,
                "hasParent": true,
                "hasChildren": false,
                "parentId": 7,
                "childrenIds": [],
                "text": "More data two-two",
                "childComments": []
            }
        ]
    }
]

The delete function works for the top level of the data structure. For nested data, the delete function is not working. What am I doing wrong?

This is the code for the recursive delete function:

const HandleDelete = function(commentObj, objId) {
    const filteredObj = commentObj.filter((ele) =>{
            if (ele.childComments.length > 0 ) {
                HandleDelete(ele.childComments, objId)
            }
            return ele.id !== objId;
    })
    return filteredObj;
}

4

Answers


  1. As mentioned by @Pointy, you aren’t doing anything with the result of the inner HandleDelete.

    What I think you want is to map over the childComments first, then filter

    const HandleDelete = function (commentArr, objId) {
      const filteredArr = commentArr.filter((ele) => ele.id !== objId);
      const filteredChildren = filteredArr.map((ele) => ({
          ...ele,
          childComments: HandleDelete(ele.childComments, objId),
        }));
      return filteredChildren;
    };
    

    EDIT: changed order of map and filter, so it deletes top level items first, so it doesn’t waste time recursing them only to throw away the result

    Login or Signup to reply.
  2. Looks like you aren’t updating the childComments property of the parent object after removing the child comment. Try updating the childComments property on the parent comment by calling your handleDelete function recursively, and setting the result as the new childComments value:

    const HandleDelete = function(commentObj, objId) {
        return commentObj.filter((ele) =>{
            if (ele.childComments.length > 0 ) {
                ele.childComments = HandleDelete(ele.childComments, objId)
            }
            return ele.id !== objId;
        });
    };
    
    Login or Signup to reply.
  3. When you modify an element inside the filter function, it can cause unexpected behavior and may produce incorrect results. This is because modifying an element can change the truthiness of the condition you are using to filter, which can lead to unexpected filtering results.

    A better way might be this

    const HandleDelete = function (commentObj, objId) {
      // create an empty array to store filtered objects
      const filteredObj = []; 
    
      for (const ele of commentObj) {
        // if the object id matches the id to be deleted
        if (ele.id === objId) { 
          // if objId is unique, you can return here since you found the object to delete
          return;
        }
        // if the object doesn't match the id to be deleted,
        // check if it has child comments and recursively call the delete function
        // passing in the child comments as the new commentObj
        // otherwise, push the object into the filteredObj array
        filteredObj.push(ele.childComments ? HandleDelete(ele.childComments, objId) : ele);
      }
    
      return filteredObj; // return the filtered array
    };
    
    
    Login or Signup to reply.
  4. Just filter without recursion, and only then apply recursion to childComments, where present:

    const HandleDelete = function(commentObj, objId) {
        const filteredObj = commentObj.filter((ele) =>{
                return ele.id !== objId;
        }).map((ele) =>{
                if (ele.childComments.length > 0 ) {
                    return HandleDelete(ele.childComments, objId)
                }
        });
        return filteredObj;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search