React Table:如何实现按Vendor分组的可折叠行?
React Table实现Vendor可折叠分组行方案
问题背景
给定以下TypeScript数据结构,需要实现带Vendor(如Vendor1、Vendor2)可折叠分组行的React Table:
export type VendorContent = { id: number; name: string; user_name: string; dob: string; }; export type VendorData = { vendor: string; rows: VendorContent[]; };
通过<DataTable defaultData={vendorData} />传入数据,当前代码因扁平化数据丢失分组信息,无法实现分组折叠功能,尝试过直接传入原数据、getSubRows、Header Groups均未满足需求。
解决方案
利用React Table的**展开折叠(useExpanded)和子行获取(getSubRows)**能力,结合自定义分组行渲染,实现需求:
1. 调整数据结构,保留分组关联
不再扁平化数据,而是将每个Vendor项作为顶层行,关联对应的子行数据:
const [data, setData] = React.useState(() => defaultData.map(item => ({ vendor: item.vendor, subRows: item.rows, isGroupRow: true // 标记为分组行,用于后续渲染区分 })) );
2. 配置React Table插件与参数
引入useExpanded插件处理展开折叠状态,同时定义getSubRows函数指定子行来源:
import { useReactTable, getCoreRowModel, useExpanded, getSubRows } from '@tanstack/react-table'; // ... const table = useReactTable({ data, columns, getCoreRowModel: getCoreRowModel(), useExpanded, // 启用展开折叠功能 getSubRows: row => row.subRows || [], // 指定子行获取逻辑 });
3. 修改列定义,添加分组列
新增分组列用于渲染展开按钮和Vendor名称,其他列保持原有配置:
const columns = [ columnHelper.display({ id: 'group', header: '', cell: ({ row }) => { if (row.original.isGroupRow) { return ( <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}> {/* 展开/折叠切换按钮 */} <button onClick={() => row.toggleExpanded()}> {row.getIsExpanded() ? '▼' : '▶'} </button> <strong>{row.original.vendor}</strong> </div> ); } return null; // 数据行该列留空 }, }), columnHelper.accessor('name', { header: () => 'Name', cell: (info) => info.renderValue(), }), columnHelper.accessor('user_name', { header: () => 'User name', cell: (info) => info.renderValue(), }), columnHelper.accessor('dob', { header: () => 'DOB', cell: (info) => info.renderValue(), }), columnHelper.display({ id: 'actions', cell: (props) => <p>test</p>, }), ];
4. 渲染表格时处理分组行跨列
在tbody渲染逻辑中,让分组行的首个单元格跨所有可见列,保证布局美观:
<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, index) => { if (row.original.isGroupRow && index === 0) { // 分组行跨列渲染 return ( <td colSpan={row.getVisibleCells().length} key={cell.id}> {cell.renderCell()} </td> ); } return <td key={cell.id}>{cell.renderCell()}</td>; })} </tr> ))} </tbody> </table>
关键说明
- 通过
isGroupRow标记区分分组行与数据行,实现差异化渲染 row.toggleExpanded()和row.getIsExpanded()用于控制和判断展开状态getSubRows告诉React Table如何从顶层行获取子行数据
内容的提问来源于stack exchange,提问作者Squiggs.
相关产品推荐
相关产品推荐

