React Tanstack Table动态列配置后行无法渲染求助
React Tanstack Table 动态列(固定列+日期列)渲染问题
我找不到任何非硬编码列的React Tanstack Table示例,想要制作一个包含1个固定列(用于描述/标签)和n个日期列的表格。
列配置(可正常渲染表头)
const newColumns = [ { id: 'rowName', accessor: 'rowName', header: 'rowName', enableSorting: true, }, ...datesFiltered.map(timestamp => ({ id: timestamp.toString(), accessor: timestamp.toString(), header: monthNames[new Date(timestamp).getMonth()] + ' ' + new Date(timestamp).getFullYear(), enableSorting: true, })), ];
但表格行完全无法渲染,以下是相关信息:
原始API数据结构
type NestedDictionary = { [key: number]: { [key: string]: number; }; };
这是一个以时间戳为键的字典,每个值是嵌套字典,嵌套字典的键是要放在表格第一列的变量。
当前数据处理代码
let arr:any = [] if (data !== null) { const allKeys = Array.from(new Set(Object.values(data).flatMap(Object.keys))); allKeys.forEach((key) => { const tableData: { [key: string]: string | number }[] = []; const row: { [key: string]: string | number } = {metric: key, id: "rowName",cell:key}; row[key] = key || '-'; tableData.push(row); Object.entries(data).forEach(([year, values]) => { if(datesFiltered.includes(Number(year))){ const row: { [key: string]: string | number } = {metric: key, id: year.toString(),cell:values[key]||"-"}; tableData.push(row); } });arr.push(tableData); }); }
表格组件代码
import React from 'react' import { flexRender, getCoreRowModel, getSortedRowModel, SortingState, useReactTable, } from '@tanstack/react-table' interface InteractiveTableProps { data:any[][]; columns:any; } export const InteractiveTable: React.FC<InteractiveTableProps> = ({data, columns}) => { const [sorting, setSorting] = React.useState<SortingState>([]) const table = useReactTable({ data, columns, state: { sorting, }, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), debugTable: true, }) console.log(table) return ( <div className="p-2 text-primary"> <div className="h-2" /> <table> <thead> {table.getHeaderGroups().map(headerGroup => ( <tr key={headerGroup.id}> {headerGroup.headers.map(header => { return ( <th key={header.id} colSpan={header.colSpan}> {header.isPlaceholder ? null : ( <div {...{ className: header.column.getCanSort() ? 'cursor-pointer select-none' : '', onClick: header.column.getToggleSortingHandler(), }} > {flexRender( header.column.columnDef.header, header.getContext() )} {{ asc: ' 🔼', desc: ' 🔽', }[header.column.getIsSorted() as string] ?? null} </div> )} </th> ) })} </tr> ))} </thead> <tbody> {table .getRowModel() .rows .map(row => { return ( <tr key={row.id}> {row.getVisibleCells().map(cell => { return ( <td key={cell.id}> {flexRender( cell.column.columnDef.cell, cell.getContext() )} </td> ) })} </tr> ) })} </tbody> </table> <div>{table.getRowModel().rows.length} Rows</div> <pre>{JSON.stringify(sorting, null, 2)}</pre> </div> ) } export default InteractiveTable;
问题核心与解决方案
问题根源在于数据格式不匹配:Tanstack Table要求data是一维对象数组(每个对象对应一行),但你当前生成的是二维数组,且行数据字段与列配置的accessor完全不对应。
1. 修正数据处理逻辑
将原始嵌套字典转换为符合要求的行数据数组:每个行对象包含固定列rowName和所有日期列的键值对。
// 正确的数据转换函数 const formatTableData = (rawData: NestedDictionary, datesFiltered: number[]) => { // 获取所有要展示的行名称(第一列内容) const allRowNames = Array.from(new Set(Object.values(rawData).flatMap(Object.keys))); // 生成每行数据 return allRowNames.map(rowName => { const row: { [key: string]: string | number } = { rowName: rowName // 对应固定列的accessor }; // 遍历筛选后的日期,填充对应列的值 datesFiltered.forEach(timestamp => { const timestampStr = timestamp.toString(); // 从原始数据中取值,无数据则填'-' row[timestampStr] = rawData[timestamp]?.[rowName] ?? '-'; }); return row; }); }; // 使用示例 const tableData = data ? formatTableData(data, datesFiltered) : [];
2. 修正表格组件的Props类型
原组件data类型定义为any[][],改为一维对象数组类型:
interface InteractiveTableProps { data: any[]; // 修正为对象数组 columns: any; }
3. 补充列配置的cell渲染逻辑(可选)
如果列配置未指定cell,表格会默认渲染字段值,也可以显式添加确保渲染正常:
const newColumns = [ { id: 'rowName', accessor: 'rowName', header: '描述/标签', enableSorting: true, cell: (info: any) => info.getValue(), }, ...datesFiltered.map(timestamp => ({ id: timestamp.toString(), accessor: timestamp.toString(), header: `${monthNames[new Date(timestamp).getMonth()]} ${new Date(timestamp).getFullYear()}`, enableSorting: true, cell: (info: any) => info.getValue(), })), ];
内容的提问来源于stack exchange,提问作者JPWilson
相关产品推荐
相关产品推荐

