如何在react-table中根据输入动态生成任意数量的列?
嘿,这个场景我之前做接口测试结果展示的时候刚好碰到过,react-table处理动态列其实非常灵活,给你分享个我实测好用的方案~
核心思路
react-table的columns配置本质就是一个数组,所以我们只需要把固定列(比如Name)和动态生成的测试用例列合并成一个数组,就能实现数量不确定的列展示了。
具体实现步骤
1. 先明确你的数据结构
假设你的数据源是这样的(两种常见情况,选符合你实际的就行):
- 情况一:每个函数结果里的测试用例是独立字段
const data = [ { name: 'FuncA', testCase1: 'Pass', testCase2: 'Fail', testCase3: 'Pass' }, { name: 'FuncB', testCase1: 'Pass', testCase2: 'Pass', testCase3: 'Fail' }, ];
- 情况二:每个函数结果里的测试用例是一个数组
const data = [ { name: 'FuncA', testResults: ['Pass', 'Fail', 'Pass'] }, { name: 'FuncB', testResults: ['Pass', 'Pass', 'Fail'] }, ];
同时你需要有一个包含所有测试用例名称的数组(比如从接口返回、或者从测试文件解析得到):
const testCases = ['Test Case 1', 'Test Case 2', 'Test Case 3']; // 如果是自定义名称也可以,比如:['边界值测试', '性能测试', '兼容性测试']
2. 动态生成Columns数组
用useMemo来缓存列配置(避免不必要的重渲染),先定义固定列,再循环生成测试用例列:
import { useTable } from 'react-table'; import React from 'react'; function TestResultTable({ data, testCases }) { const columns = React.useMemo(() => { // 固定的Name列 const fixedColumns = [ { Header: 'Name', accessor: 'name', // 对应data里的name字段 width: 150, // 可以自定义宽度 }, ]; // 动态生成测试用例列 const dynamicTestColumns = testCases.map((testName, index) => ({ Header: testName, // 根据你的数据结构选对应的accessor // 情况一:对应独立字段 accessor: `testCase${index + 1}`, // 情况二:从testResults数组取对应索引的值 // accessor: (row) => row.testResults[index], // 可选:自定义单元格渲染(比如给Pass/Fail加颜色) Cell: ({ value }) => ( <span className={value === 'Pass' ? 'text-green-600 font-medium' : 'text-red-600 font-medium'}> {value} </span> ), // 可选:开启排序、过滤等功能,和固定列一样配置 sortable: true, filter: true, })); // 合并固定列和动态列 return [...fixedColumns, ...dynamicTestColumns]; }, [testCases]); // 依赖testCases,当测试用例数量/名称变化时自动更新列 // 正常初始化react-table const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable({ columns, data, }); // 渲染表格(和react-table基础用法一致) return ( <table {...getTableProps()} className="border-collapse w-full"> <thead> {headerGroups.map(headerGroup => ( <tr {...headerGroup.getHeaderGroupProps()}> {headerGroup.headers.map(column => ( <th {...column.getHeaderProps()} className="border p-2 bg-gray-50"> {column.render('Header')} </th> ))} </tr> ))} </thead> <tbody {...getTableBodyProps()}> {rows.map(row => { prepareRow(row); return ( <tr {...row.getRowProps()}> {row.cells.map(cell => ( <td {...cell.getCellProps()} className="border p-2"> {cell.render('Cell')} </td> ))} </tr> ); })} </tbody> </table> ); }
3. 使用组件
不管你的测试用例数量是3个还是10个,只要把对应的data和testCases传给组件就行:
// 比如测试用例数量为5的情况 const testCases5 = ['Test Case 1', 'Test Case 2', 'Test Case 3', 'Test Case 4', 'Test Case 5']; const data5 = [/* 对应5个测试用例的结果数据 */]; <TestResultTable data={data5} testCases={testCases5} />
额外提示
- 如果你的测试用例名称是从数据里动态提取的(比如不知道testCases数组,只能从data的第一个条目里取),可以这样获取:
const testCases = Object.keys(data[0]).filter(key => key !== 'name'); - 动态列的配置完全可以和固定列一样,比如加宽度、自定义表头样式、排序过滤逻辑等,没有任何限制。
内容的提问来源于stack exchange,提问作者mikasa
相关产品推荐
相关产品推荐

