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

如何基于API返回的JSON响应在React中渲染动态HTML表格

需求说明

我需要遍历表格JSON的字段值生成如下结构的HTML表格:

<div>
      <table>
        <tr>
            <td>Rows</td>
            <td>List 1 </td>
            <td>List 2 </td>
        </tr>
        <tr>
            <td>Row 1</td>
            <td>task 1, task 2</td>
            <td>task 3</td>
        </tr>
        <tr>
            <td>Row 2</td>
            <td>task 4</td>
            <td>task 5, task 6</td>
        </tr>
      </table>
    </div>

高层逻辑是遍历JSON中的rows,示例JSON包含2行;因为table.lists有list1、list2两个值,每行对应生成2个额外列。行单元格的值来自JSON的table.data部分,该部分通过rowId、listId关联对应taskId。

现有React组件代码
import React, { useEffect, useState, useMemo } from 'react';
import { useAppSelector, useAppDispatch } from '../../app/hooks';
import {
  selectTable,
  fetchTableAsync,
} from './tableSlice';
import {
  DragDropContext,
  Draggable,
  Droppable,
  DroppableProvided,
  DraggableLocation,
  DropResult,
  DroppableStateSnapshot, DraggableProvided, DraggableStateSnapshot
} from 'react-beautiful-dnd';

export function Table() {
  const table = useAppSelector(selectTable);
  const dispatch = useAppDispatch();

 
  useEffect(() => {
    dispatch(fetchTableAsync(""))
  }, []);

  console.log('select table value is: ');
  console.log(JSON.stringify(table));

  return (
    <div>
      <table>
        <tr>
            <td>Rows</td>
            <td>List 1 </td>
            <td>List 2 </td>
        </tr>
        <tr>
            <td>Row 1</td>
            <td>task 1, task 2</td>
            <td>task 3</td>
        </tr>
        <tr>
            <td>Row 2</td>
            <td>task 4</td>
            <td>task 5, task 6</td>
        </tr>
      </table>
    </div>
  );
}
API返回JSON结构
{
    "table": {
        "id": "aecf78db-e893-40e7-8a5a-e4150cc5129c",
        "data": {
            "row1": {
                "list1": [
                    {
                        "task1": {
                            "sort": 1
                        }
                    },
                    {
                        "task2": {
                            "sort": 2
                        }
                    }
                ],
                "list2": [
                    {
                        "task3": {
                            "sort": 1
                        }
                    }
                ]
            
            },
            "row2": {
                "list1": [
                    {
                        "task4": {
                            "sort": 1
                        }
                    }
                ],
                "list2": [
                    {
                        "task5": {
                            "sort": 1
                        }
                    },
                    {
                        "task6": {
                            "sort": 1
                        }
                    }
                ]
            }
        }
    },
    "lists": [
        {
            "list1": {
                "name": "List 1",
                "sort": 1
            }
        },
        {
            "list2": {
                "name": "List 2",
                "sort": 2
            }
        }
    ],
    "rows":
    {
        "row1": {
            "title": "Row 1"
        },
        "row2": {
            "title": "Row 2"
        }
    },
    "tasks":
    {
        "task1": {
            "title": "task 1"
        },
        "task2": {
            "title": "task 2"
        },
        "task3": {
            "title": "task 3"
        },
        "task4": {
            "title": "task 4"
        },
        "task5": {
            "title": "task 5"
        },
        "task6": {
            "title": "task 6"
        }
    }
}
实现代码

直接复用你设计的键值对查询结构,所有关联查找都是O(1)复杂度,保证大数据量下的渲染效率:

export function Table() {
  const table = useAppSelector(selectTable);
  const dispatch = useAppDispatch();

  useEffect(() => {
    dispatch(fetchTableAsync(""))
  }, []);

  // 提前计算排序后的列表,避免渲染时重复计算
  const sortedLists = useMemo(() => {
    if (!table?.lists) return []
    return table.lists.sort((a, b) => {
      const aKey = Object.keys(a)[0]
      const bKey = Object.keys(b)[0]
      return a[aKey].sort - b[bKey].sort
    })
  }, [table?.lists])

  // 数据未加载完成返回占位
  if (!table || !table.rows || !sortedLists.length) return <div>加载中...</div>

  return (
    <div>
      <table>
        {/* 表头渲染 */}
        <tr>
          <td>Rows</td>
          {sortedLists.map(listItem => {
            const listId = Object.keys(listItem)[0]
            return <td key={listId}>{listItem[listId].name}</td>
          })}
        </tr>
        {/* 逐行渲染 */}
        {Object.entries(table.rows).map(([rowId, rowInfo]) => (
          <tr key={rowId}>
            <td>{rowInfo.title}</td>
            {/* 每行渲染所有列表对应的列 */}
            {sortedLists.map(listItem => {
              const listId = Object.keys(listItem)[0]
              // 直接通过键取对应行对应列的任务列表
              const taskList = table.table.data?.[rowId]?.[listId] || []
              // 按sort排序后拼接任务名称
              const taskNames = taskList
                .sort((a, b) => {
                  const aTaskId = Object.keys(a)[0]
                  const bTaskId = Object.keys(b)[0]
                  return a[aTaskId].sort - b[bTaskId].sort
                })
                .map(taskItem => {
                  const taskId = Object.keys(taskItem)[0]
                  return table.tasks[taskId]?.title || ''
                })
                .filter(Boolean)
                .join(', ')
              return <td key={`${rowId}-${listId}`}>{taskNames}</td>
            })}
          </tr>
        ))}
      </table>
    </div>
  );
}

后续如果要接入拖拽功能,只需要在对应单元格内嵌套Droppable、Draggable组件即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 10:45:03