You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何递归移除对象中的子对象?React树形表格拆分项移除后的节点处理问题

解决树形表格移除拆分项时递归删除子节点的问题

看起来你的核心问题是移除拆分项时,没有正确遍历树形结构删除对应节点,也没同步更新父节点的展开状态。我来帮你一步步修复代码:

问题分析

你的现有recursiveDelete和recursionDel函数只是简单遍历节点,没有实际执行删除逻辑;而且移除拆分后,没有处理父节点的isExpanded状态回退,也没清理空的子节点结构。

解决方案

1. 重构递归删除函数

写一个能真正遍历树形结构、删除目标拆分节点并更新父状态的函数:

const recursiveDelete = (data, removedSplit) => {
  // 过滤当前层级中属于被移除拆分的节点
  const filteredRows = data.filter(row => row.currentSplit !== removedSplit);
  
  return filteredRows.map(row => {
    const updatedRow = {...row};
    // 重新计算当前节点的nextSplit
    updatedRow.nextSplit = checkIfSplitExist(updatedRow.currentSplit);
    
    // 递归处理子节点
    if (updatedRow.children) {
      const processedChildren = recursiveDelete(updatedRow.children, removedSplit);
      // 如果子节点被全部删除,重置父节点状态
      if (processedChildren.length === 0) {
        updatedRow.isExpanded = false;
        delete updatedRow.children;
      } else {
        updatedRow.children = processedChildren;
      }
    }
    
    // 如果当前节点没有后续拆分,强制关闭展开状态
    if (!updatedRow.nextSplit) {
      updatedRow.isExpanded = false;
      delete updatedRow.children;
    }
    
    return updatedRow;
  });
};

2. 修正拆分项删除逻辑

在addNewSplit函数中,替换原来的删除处理逻辑:

const addNewSplit = (split) => {
  const i = _.findIndex(this.state.splitOption, el => el === split);
  if(i === -1) {
    this.setState(
      { splitOption: [...this.state.splitOption, split] },
      () => {
        const rowData = recursiveUpdate(this.state.data);
        this.setState({ data: rowData });
      }
    );
  } else {
    const prevSplitOption = [...this.state.splitOption];
    prevSplitOption.splice(i, 1);
    this.setState(
      { splitOption: prevSplitOption },
      () => {
        // 使用新的递归删除函数处理数据
        const updatedData = recursiveDelete(this.state.data, split);
        this.setState({ data: updatedData });
      }
    );
  }
};

3. 修复recursiveUpdate函数

原来的函数没有返回更新后的节点,导致添加拆分时状态更新无效:

const recursiveUpdate = (data) => {
  return data.map(row => recursion(row));
};

4. 完善recursion函数(确保状态同步)

确保添加拆分时,所有节点的nextSplit和展开状态正确:

const recursion = (obj) => {
  const row = {...obj};
  row.nextSplit = checkIfSplitExist(row.currentSplit);
  
  // 如果没有后续拆分,强制关闭展开并清理子节点
  if (!row.nextSplit) {
    row.isExpanded = false;
    delete row.children;
  }
  
  if (row.children && row.children.length > 0) {
    row.children = row.children.map(v => recursion(v));
  }
  return row;
};

5. 修正渲染文本错误

在ExpandableTableRow中,把{row.split}改成{row.name}(你的数据里没有split字段):

<td>
  <ExpandCollapsToggle row={row} expandRow={expandRow} collapseRow={collapseRow}/>{" "}
  {row.name} - {row.id}
</td>

测试验证

现在按照你的复现步骤测试:

  1. 点击"camp name"添加拆分,展开顶级节点看到子行;
  2. 添加"os"或"country",二级节点会显示展开图标;
  3. 移除"camp name",所有属于该拆分层级的节点(包括子节点)会被删除,顶级节点的图标自动切回+。

这样就能实现你需要的移除拆分项时递归删除对应子节点并更新状态的效果了。

内容的提问来源于stack exchange,提问作者Janak Prajapati

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 09:37:37