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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:14:50