React中动态映射表头与行时表头重复问题排查
问题描述
我获取到如下结构的JSON响应数据:
[ { "DESCRIPTION": "OER", "OER_HI": 23.23650286618332, "OER_BI": 23.419567144988942, "OER_SBI": 23.74404977161088 }, { "DESCRIPTION": "CPO Production", "OER_HI": 1046.17, "OER_BI": 10538.517, "OER_SBI": 87788.887 }, { "DESCRIPTION": "CPO Dispatch", "OER_HI": 1489.6000000000001, "OER_BI": 9145.67, "OER_SBI": 81187.22 }, { "DESCRIPTION": "CPO Stock", "OER_HI": 12032.43, "OER_BI": null, "OER_SBI": null }, { "DESCRIPTION": "Total Oil, Losses/FFB", "OER_HI": 1.4761952, "OER_BI": 1.4469707631313098, "OER_SBI": 1.44239404903668 } ]
我期望在React中动态映射生成表头为JSON键、表行为对应值的表格,但使用以下代码实现后,表头出现重复的JSON键值,请问代码中存在什么问题?
import React, {useEffect} from "react"; import {connect, useDispatch} from "react-redux"; import {Table, Header} from "semantic-ui-react"; import {fetchChart8} from "../redux/actions"; import LoadingStatus from "./templates/LoadingStatus"; import _ from "lodash" const TableChart = ({chart_8}) => { const dispatch = useDispatch(); let testMap = chart_8?.map(data => { return Object.keys(data) }) let description = testMap[0] let oer_hi = testMap[0] let oer_bi = testMap[0] let oer_sbi = testMap[0] useEffect(() => { dispatch(fetchChart8()) }, [dispatch]); if (_.isNull(chart_8)) return <LoadingStatus/>; return ( <div> <Header> <Header.Content>CPO</Header.Content> </Header> <Table celled> <Table.Header> <Table.Row> <Table.HeaderCell> {description} </Table.HeaderCell> <Table.HeaderCell> {oer_hi} </Table.HeaderCell> <Table.HeaderCell> {oer_bi} </Table.HeaderCell> <Table.HeaderCell> {oer_sbi} </Table.HeaderCell> </Table.Row> </Table.Header> <Table.Body> {chart_8.map((data) => { return ( <Table.Row> <Table.Cell> {data["DESCRIPTION"]} </Table.Cell> <Table.Cell> {data["OER_HI"]} </Table.Cell> <Table.Cell> {data["OER_BI"]} </Table.Cell> <Table.Cell> {data["OER_SBI"]} </Table.Cell> </Table.Row> ) })} </Table.Body> </Table> </div> ); }; const mapStateToProps = (state) => { return { chart_8: state.dashboard.chart_8 }; }; export default connect(mapStateToProps, { fetchChart8 })(TableChart);
问题分析与修复
核心问题
你的表头逻辑完全错误:
testMap = chart_8?.map(data => Object.keys(data))会生成一个二维数组,每个元素都是单条数据的完整键数组(比如每个元素都是["DESCRIPTION", "OER_HI", "OER_BI", "OER_SBI"])。- 你把
description、oer_hi、oer_bi、oer_sbi全赋值成testMap[0]——也就是完整的键数组,这导致每个表头单元格都渲染了整个键列表,自然出现重复的键值。
修复方案
只需要取第一条数据的键数组作为表头来源,然后遍历这个数组生成表头单元格即可。如果想确保表头顺序绝对稳定,也可以手动指定键的顺序(Object.keys的顺序在ES6+是稳定的,但手动指定更可控)。
修正后的代码:
import React, { useEffect } from "react"; import { connect, useDispatch } from "react-redux"; import { Table, Header } from "semantic-ui-react"; import { fetchChart8 } from "../redux/actions"; import LoadingStatus from "./templates/LoadingStatus"; import _ from "lodash"; const TableChart = ({ chart_8 }) => { const dispatch = useDispatch(); useEffect(() => { dispatch(fetchChart8()); }, [dispatch]); if (_.isNull(chart_8)) return <LoadingStatus />; // 取第一条数据的键作为表头,或者手动指定顺序更可控 const tableHeaders = chart_8.length > 0 ? Object.keys(chart_8[0]) : []; // 可选:手动指定表头顺序 const tableHeaders = ["DESCRIPTION", "OER_HI", "OER_BI", "OER_SBI"]; return ( <div> <Header> <Header.Content>CPO</Header.Content> </Header> <Table celled> <Table.Header> <Table.Row> {tableHeaders.map((header) => ( <Table.HeaderCell key={header}>{header}</Table.HeaderCell> ))} </Table.Row> </Table.Header> <Table.Body> {chart_8.map((data, index) => ( <Table.Row key={index}> {tableHeaders.map((key) => ( <Table.Cell key={key}> {data[key] ?? "-"} {/* 处理null值,用短横线替代显示 */} </Table.Cell> ))} </Table.Row> ))} </Table.Body> </Table> </div> ); }; const mapStateToProps = (state) => { return { chart_8: state.dashboard.chart_8, }; }; export default connect(mapStateToProps, { fetchChart8 })(TableChart);
关键优化点
- 直接从第一条数据提取表头键数组,遍历生成表头单元格,避免重复渲染。
- 表格行也通过遍历表头键生成单元格,实现完全动态,不需要硬编码每个字段。
- 增加
data[key] ?? "-"处理null值,让表格显示更友好。 - 给每个动态生成的元素加上
key属性,符合React列表渲染规范。
内容的提问来源于stack exchange,提问作者john_smith
相关产品推荐
相关产品推荐

