React JS递归处理数据触发RangeError: Maximum call stack size exceeded
栈溢出报错的核心成因
你的递归终止逻辑本身设计方向是对的,但有三类问题会导致递归无法正常终止,最终触发RangeError:
- 原始层级数据存在环形关联/自引用
这是最常见的栈溢出诱因:如果数据中出现节点自环(单个节点的父id等于自身id)、多节点闭环(比如A的父是B,B的父是A),每次执行filter查找子节点时,都能匹配到至少一个关联项,递归会无限向下嵌套调用,直到JS引擎的调用栈被占满。
举个最简单的触发例子:只要数据里存在{id:1, name:'a', idfather:1}这类自引用节点,代码每跑一次递归就会把自己作为子节点再次传入,永远碰不到“无匹配子节点”的终止分支。 - 代码字段拼写前后完全不统一
你在三处涉及父id关联的位置用了完全不同的字段名,没有任何一致性:- 读取原数据父id时:写的是
data.idfahter(将father错拼为fahter,少了字母t) - 给结果对象赋值父id时:写的是
idfhater(将idFather错拼为idfhater,多了字母h、漏了结尾的r) - 查找子节点做相等判断时:写的是
item.idfather(使用了全小写的idfather命名)
如果原始数据的父id字段和你filter判断用的字段名不一致,会导致匹配逻辑完全失效;如果字段名匹配错误意外让本不该被识别为子节点的项被筛出来,也会打破递归终止条件。
- 读取原数据父id时:写的是
- 额外的非报错类功能bug
你目前的代码在拿到递归返回值时,是把整个子节点数组作为一个独立元素push到结果里,最终生成的是多层嵌套的数组结构,不是你预期的带缩进的平铺节点列表,只不过这个问题不会导致栈溢出。
可直接落地的修正方案
- 前置数据校验:在正式递归处理前,先遍历全量节点,排查自环、跨节点成环的异常数据,从源头避免无限递归。
- 统一字段命名:把所有涉及父id的字段名做统一(比如全部用
idFather作为键名),保证读取、存储、匹配逻辑用的是同一个字段。 - 修正递归结果的合并逻辑:用展开运算符把递归返回的子节点列表合并到当前结果数组中,避免生成嵌套结构。
- 可选兜底方案:如果业务场景下原始数据不可控,可以增加递归深度参数,当深度超过合理阈值(比如100层,远大于常规业务的层级数)时自动终止递归,避免栈溢出。
修正后的参考代码:
function orderRecursive(Data, tab = "") { let orderData = []; for (const data of Data) { orderData.push({ id : data.id, name: tab + data.name, idFather : data.idFather // 统一字段拼写 }); // 统一字段后做子节点匹配 const children = Data.filter(item => item.idFather === data.id); if(children.length > 0) { // 展开递归结果,避免嵌套数组 orderData.push(...orderRecursive(children, tab + "\t")); } } return orderData; }
内容的提问来源于stack exchange,提问作者user15242898
相关产品推荐
相关产品推荐

