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

如何通用生成MUI DataGrid动态Rows(非硬编码字段)

问题描述

以下是MUI DataGrid文档v7.10.0中的示例:

const tempColumns: GridColDef[] = [
  { field: "id", headerName: "ID", width: 90 },
  {
    field: "firstName",
    headerName: "First name",
    width: 150,    
  },
  {
    field: "lastName",
    headerName: "Last name",
    width: 150,    
  },
];

const rows = [
  { id: 1, lastName: 'Snow', firstName: 'Jon' },
  { id: 2, lastName: 'Lannister', firstName: 'Cersei' },
  { id: 3, lastName: 'Lannister', firstName: 'Jaime' },  
];

上述示例中,rows是通过硬编码值和字段初始化的。

现在Columns将动态生成(支持用户自定义),Columns的定义数据来自API接口,Rows的数据来自一个或多个API接口。

如何通过获取API数据,拼接出可传入DataGrid组件rows属性的对象数组?

我猜想可以通过解析Columns数组获取所用字段名称,但具体该如何操作?

我不能直接采用以下写法(因为我不知道"field"和"field2"的存在,且字段可能多达上百个,这种方式不可行):

rows.push({
   id: 1,
   field: "some value",
   field2: "some value"
})

是否存在通用的实现方式?


解决方案

核心思路

通过解析API返回的columns数组提取所有字段名,再将API返回的原始数据映射为DataGrid要求的结构——确保每一行对象只包含columns中定义的字段,同时保证行唯一标识(默认是id字段)存在。

具体实现步骤

  1. 提取Columns中的字段列表
    先从API获取columns数据,提取所有field字段,同时确认行唯一标识字段(默认id)存在,若不存在需手动处理或配置DataGrid的getRowId属性指定其他唯一字段。
// 从API获取动态列配置
const apiColumns: GridColDef[] = await fetch('/api/columns').then(res => res.json());
// 提取所有需要的字段名
const requiredFields = apiColumns.map(col => col.field);

// 确保行唯一标识存在(DataGrid强制要求)
if (!requiredFields.includes('id')) {
  // 若API未返回id字段,可手动添加,或后续配置getRowId
  requiredFields.push('id');
}
  1. 映射原始数据为DataGrid可用格式
    遍历API返回的原始数据,仅保留requiredFields中定义的字段,生成符合要求的行对象。如果数据来自多个API,先通过唯一标识合并再映射。
// 从API获取原始行数据
const rawRows = await fetch('/api/rows').then(res => res.json());

// 映射为DataGrid兼容的行数组
const dataGridRows = rawRows.map(rawRow => {
  const row: Record<string, any> = {};
  requiredFields.forEach(field => {
    // 从原始数据取对应字段值,无值则设为null避免渲染异常
    row[field] = rawRow[field] ?? null;
  });
  return row;
});
  1. 多API数据合并(可选)
    若行数据来自多个API,可通过唯一标识(如id)先合并数据:
// 从两个API获取数据
const basicRows = await fetch('/api/basic-rows').then(res => res.json());
const extendedRows = await fetch('/api/extended-rows').then(res => res.json());

// 将扩展数据转为Map,方便快速查找
const extendedDataMap = new Map(extendedRows.map(row => [row.id, row]));

// 合并基础数据与扩展数据
const mergedRawRows = basicRows.map(basicRow => ({
  ...basicRow,
  ...extendedDataMap.get(basicRow.id)
}));

// 再执行前面的映射逻辑生成DataGrid行数组
const dataGridRows = mergedRawRows.map(rawRow => {
  const row: Record<string, any> = {};
  requiredFields.forEach(field => {
    row[field] = rawRow[field] ?? null;
  });
  return row;
});
  1. 字段名映射兼容(可选)
    若API返回的原始数据字段名与columns中的field不匹配,可在columns中添加自定义属性(如apiField)来做映射:
// 假设API返回的columns包含apiField属性,对应原始数据的字段名
const apiColumns: (GridColDef & { apiField?: string })[] = await fetch('/api/columns').then(res => res.json());

const dataGridRows = rawRows.map(rawRow => {
  const row: Record<string, any> = {};
  apiColumns.forEach(col => {
    // 优先使用apiField匹配原始数据字段,无则用field
    const sourceField = col.apiField ?? col.field;
    row[col.field] = rawRow[sourceField] ?? null;
  });
  // 确保行唯一标识存在
  row.id = rawRow.id ?? rawRow[apiColumns.find(col => col.field === 'id')?.apiField] ?? null;
  return row;
});
  1. DataGrid组件使用
    最后将处理好的列和行数据传入组件:
<DataGrid
  columns={apiColumns}
  rows={dataGridRows}
  // 若未使用id作为唯一标识,需配置getRowId
  // getRowId={(row) => row.yourUniqueKey}
/>

关键注意事项

  • 行唯一标识:DataGrid要求每行必须有唯一标识,默认是id字段,若使用其他字段需通过getRowId属性指定。
  • 空值处理:原始数据中不存在的字段建议设为null或空字符串,避免组件渲染异常。
  • 类型安全:TypeScript项目中可通过定义接口约束原始数据和行数据的类型,避免类型错误。

内容的提问来源于stack exchange,提问作者Okta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:07:18