React多级评论递归filter删除函数嵌套失效问题排查
N层级React应用递归删除函数失效问题排查
问题描述
我有一个React N层级应用,使用Array.prototype.filter()实现递归删除函数。数据为对象数组,每个对象可能包含childComments子数据数组。目前该函数仅能删除顶层数据,嵌套层级的数据删除完全失效。
数据结构示例
[ { "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": [] } ] } ]
当前递归删除代码
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; }
问题原因
核心问题是递归处理子数组后,没有将结果赋值回原对象的childComments属性:
- 调用
HandleDelete(ele.childComments, objId)时,虽然会递归过滤子数组,但返回的新数组没有被保存,原元素的childComments仍然是未修改的旧数组。 - 外层
filter仅负责过滤当前层级的元素,不会自动更新子层级的数据结构,导致子层级的删除操作无法体现在最终返回的结果中。
修复方案
需要在递归处理子数组后,将过滤后的子数组重新赋值给当前元素(遵循React不可变数据原则,通过浅拷贝更新对象),修改后的代码如下:
const HandleDelete = function(commentObj, objId) { // 先过滤当前层级中需要删除的元素 return commentObj.filter(ele => ele.id !== objId) // 对剩余元素递归处理子评论,更新childComments .map(item => { if (item.childComments.length > 0) { return { ...item, childComments: HandleDelete(item.childComments, objId) }; } return item; }); }
逻辑说明
- 先用
filter移除当前层级中id匹配的元素; - 再用
map遍历剩余元素,对包含子评论的元素,递归调用HandleDelete处理子数组,并通过对象浅拷贝的方式更新childComments属性; - 确保每一层级的子评论删除结果都被正确保留到最终的数据结构中。
内容的提问来源于stack exchange,提问作者davidhartman00
相关产品推荐
相关产品推荐

