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

React-Table中能否通过两个API分别获取表头与数据字段?如何实现?

React-Table中能否通过两个API分别获取表头与数据字段?如何实现?

嘿,当然可以用两个独立API分别获取表头配置和表格数据啦!你的思路方向是对的,只是代码里有几个小细节需要调整,我帮你梳理一下~

先说说你代码里的几个问题

  1. 表头处理错误:你用const headers = header.map(col => ({Header: col.ColumnName}))生成了一个对象数组,但React Table的Header属性需要的是字符串,不是对象。而且你把整个headers数组直接赋值给单个列的Header,这会导致表头渲染出[object Object]这类错误内容。
  2. useMemo依赖缺失:columns的useMemo依赖项是空数组,这样当header和data加载完成后,columns不会重新计算,表格也不会更新。
  3. 缺少加载状态处理:API请求是异步的,在数据没返回前直接调用map可能会触发报错。

调整后的实现方案

下面是修正后的完整代码,我会把关键调整点标注出来:

App.js 代码

import { useState, useEffect, useMemo } from 'react';
import ActiveTable from './ActiveTable';

function App() {
  const [data, setData] = useState([]);
  const [header, setHeader] = useState([]);
  const [isLoading, setIsLoading] = useState(true); // 新增加载状态,避免空数据报错

  const fetchData = async () => {
    const response = await fetch('something');
    const resData = await response.json();
    setData(resData);
  };

  const fetchHeader = async () => {
    const response = await fetch('anything');
    const resData = await response.json();
    setHeader(resData);
  };

  useEffect(() => {
    const fetchAllData = async () => {
      // 用Promise.all同时发起两个API请求,提升加载效率
      await Promise.all([fetchData(), fetchHeader()]);
      setIsLoading(false); // 所有数据加载完成后关闭加载状态
    };
    fetchAllData();
  }, []);

  // 动态生成表格列:结合API返回的表头和固定列配置
  const columns = useMemo(() => {
    // 把API返回的表头数据转换成React Table需要的列格式
    const dynamicColumns = header.map(col => ({
      Header: col.ColumnName,
      accessor: col.ColumnName, // 这里假设表头的ColumnName和数据里的字段名对应,不对应需要调整
    }));

    // 固定列(比如你的图片列)可以单独定义,再和动态列合并
    const fixedColumns = [
      {
        Header: 'Logo', // 如果这个表头也需要从API获取,就从header数组里匹配对应字段
        accessor: 'BusinessPartnerLogoUrl',
        Cell: (cell) => (
          <img 
            src={cell.row.original.BusinessPartnerLogoUrl} 
            width={86} 
            alt="Partner Logo" 
          />
        )
      }
    ];

    // 合并固定列和动态列,顺序可按需调整
    return [...fixedColumns, ...dynamicColumns];
  }, [header]); // 依赖header,表头变化时自动重新生成列配置

  // 加载中显示提示
  if (isLoading) {
    return <div>加载中,请稍候...</div>;
  }

  return (
    <>
      <div className="container">
        <div className="row mt-2">
          <ActiveTable columns={columns} data={data}/>
        </div>
      </div>
    </>
  );
}

export default App;

ActiveTable.js 代码

你的这部分代码基本没问题,只需要确保在数据未加载完成时不渲染表格即可(我们已经在App.js里处理了加载状态,所以这里可以保持原样):

// 保持你原来的代码即可,比如:
import { Box } from '@mui/material'; // 假设你用了MUI组件
import TitleTable from './TitleTable';
import FilterButton from './FilterButton';
import ActionButton from './ActionButton';
import LegendaTable from './LegendaTable';
import { useTable } from 'react-table';

export default function ActiveTable({ columns, data }) {
  const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    allColumns
  } = useTable({ columns, data });

  return (
    <Box>
      <TitleTable color="#009FB5">Aktivní smlouvy</TitleTable>
      <Table {...getTableProps()}>
        <TableHead>
          {headerGroups.map(headerGroup => (
            <TableRow {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps()}>{column.render("Header")}</th>
              ))}
              <th><FilterButton filterColumns={allColumns} /></th>
            </TableRow>
          ))}
        </TableHead>
        <tbody {...getTableBodyProps()}>
          {rows.map((row, i) => {
            prepareRow(row);
            return (
              <TableRow {...row.getRowProps()} className="b-left-table tablerow-hover">
                {row.cells.map(cell => (
                  <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
                ))}
                <td><ActionButton/></td>
              </TableRow>
            );
          })}
        </tbody>
      </Table>
      <LegendaTable/>
    </Box>
  );
}

额外说明

如果你的表头API返回的字段名和数据里的accessor不匹配(比如表头显示“合作伙伴Logo”,但数据字段是BusinessPartnerLogoUrl),可以让表头API返回包含accessor的结构,比如:

// 表头API返回示例
[
  {"ColumnName": "合作伙伴Logo", "accessor": "BusinessPartnerLogoUrl"},
  {"ColumnName": "产品名称", "accessor": "ProducText"}
]

然后在生成动态列时改成:

const dynamicColumns = header.map(col => ({
  Header: col.ColumnName,
  accessor: col.accessor,
}));

备注:内容来源于stack exchange,提问作者pathy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 14:52:38