如何按managerName重组嵌套数组适配@tanstack/react-table?
按managerName分组生成嵌套结构适配@tanstack/react-table多级展开
先明确数据结构示例
初始输入数据
const initialData = [ { managerName: "王经理", name: "张三", goalName: "Q3销售目标", subRows: [ { task: "完成客户拜访", progress: 80 }, { task: "提交销售报告", progress: 100 } ] }, { managerName: "王经理", name: "李四", goalName: "Q3销售目标", subRows: [ { task: "跟进意向客户", progress: 60 } ] }, { managerName: "李经理", name: "王五", goalName: "Q3运营目标", subRows: [ { task: "优化用户路径", progress: 70 } ] } ];
目标嵌套结构(适配react-table展开)
const targetData = [ { managerName: "王经理", isManagerRow: true, // 自定义标识区分父行 subRows: [ { name: "张三", goalName: "Q3销售目标", subRows: [ { task: "完成客户拜访", progress: 80 }, { task: "提交销售报告", progress: 100 } ] }, { name: "李四", goalName: "Q3销售目标", subRows: [ { task: "跟进意向客户", progress: 60 } ] } ] }, { managerName: "李经理", isManagerRow: true, subRows: [ { name: "王五", goalName: "Q3运营目标", subRows: [ { task: "优化用户路径", progress: 70 } ] } ] } ];
实现分组函数
用reduce完成分组转换,逻辑简洁高效:
function groupByManager(data) { // 第一步:按managerName聚合子行 const groupedMap = data.reduce((acc, item) => { const manager = item.managerName; if (!acc[manager]) { acc[manager] = []; } // 移除子行中的managerName字段,避免冗余 const { managerName, ...restItem } = item; acc[manager].push(restItem); return acc; }, {}); // 第二步:转换为react-table需要的嵌套数组结构 return Object.entries(groupedMap).map(([managerName, subRows]) => ({ managerName, isManagerRow: true, // 自定义标识,用于列渲染时区分层级 subRows })); } // 调用生成嵌套数据 const nestedTableData = groupByManager(initialData);
在@tanstack/react-table中配置使用
列定义(适配多层级显示)
import { useReactTable, createColumnHelper } from '@tanstack/react-table'; const columnHelper = createColumnHelper(); const columns = [ // 展开按钮列 columnHelper.display({ id: 'expand', header: '', cell: (info) => { if (info.row.getCanExpand()) { return ( <button onClick={() => info.row.toggleExpanded()}> {info.row.getIsExpanded() ? '▼' : '▶'} </button> ); } return null; }, }), // 经理列(仅顶层父行显示) columnHelper.accessor('managerName', { header: '直属经理', cell: (info) => info.row.original.isManagerRow ? info.getValue() : '', }), // 员工列(仅员工行显示) columnHelper.accessor('name', { header: '员工姓名', cell: (info) => !info.row.original.isManagerRow ? info.getValue() : '', }), // 目标列(仅员工行显示) columnHelper.accessor('goalName', { header: '目标名称', cell: (info) => !info.row.original.isManagerRow ? info.getValue() : '', }), // 任务列(仅最底层子行显示) columnHelper.accessor('task', { header: '具体任务', cell: (info) => info.row.original.task ? info.getValue() : '', }), // 进度列(仅最底层子行显示) columnHelper.accessor('progress', { header: '进度(%)', cell: (info) => info.row.original.progress ? info.getValue() : '', }), ];
组件内初始化表格
function MultiLevelTable() { const table = useReactTable({ data: nestedTableData, columns, enableExpanding: true, // 必须开启展开功能 // 可选:默认展开所有父行 initialState: { expanded: {} }, }); // 基础表格渲染(省略样式,可自行添加) return ( <table> <thead> {table.getHeaderGroups().map(headerGroup => ( <tr key={headerGroup.id}> {headerGroup.headers.map(header => ( <th key={header.id}>{header.renderHeader()}</th> ))} </tr> ))} </thead> <tbody> {table.getRowModel().rows.map(row => ( <tr key={row.id}> {row.getVisibleCells().map(cell => ( <td key={cell.id}>{cell.renderCell()}</td> ))} </tr> ))} </tbody> </table> ); }
额外说明
- 如果需要多层嵌套分组(比如先按manager,再按goalName),可以在
reduce中嵌套二次分组逻辑 isManagerRow是自定义标识,可根据需求调整字段名,核心作用是区分不同层级的行,控制列内容显示- 如果原始数据的
subRows已经符合react-table的子行格式,直接嵌套即可,无需额外处理
内容的提问来源于stack exchange,提问作者SDK
相关产品推荐
相关产品推荐

