React Table组件适配嵌套结构JSON API数据展示问题
错误原因
原有组件的RenderRow方法直接将字段值放入<td>中渲染,当值为嵌套对象时,React无法直接将对象作为子元素渲染,因此抛出错误。
修改方案
提供两种可选实现,可根据需求选择:
方案1:保留原有表头,格式化嵌套对象内容
不需要改动表头结构,嵌套字段会自动格式化为可读字符串展示,适配两种数据结构:
// 新增工具函数:处理单元格值 const formatCellValue = (value) => { // 基础类型直接返回 if (typeof value !== 'object' || value === null) { return value; } // 数组/对象转成格式化JSON字符串,也可以自定义展示格式 return <pre>{JSON.stringify(value, null, 2)}</pre>; } const RenderRow = (props) => { return props.keys.map((key, index) => { // 修正key为字段名+索引,避免key重复/无效 return <td key={`${key}_${index}`}>{formatCellValue(props.data[key])}</td>; }) } export default class Table extends React.Component { constructor(props){ super(props); this.getHeader = this.getHeader.bind(this); this.getRowsData = this.getRowsData.bind(this); this.getKeys = this.getKeys.bind(this); } getKeys = function(){ return Object.keys(this.props.data[0]); } getHeader = function(){ var keys = this.getKeys(); return keys.map((key, index)=>{ return <th key={key}>{key.toUpperCase()}</th> }) } getRowsData = function(){ var items = this.props.data; var keys = this.getKeys(); return items.map((row, index)=>{ return <tr key={index}><RenderRow data={row} keys={keys}/></tr> }) } render() { return ( <div> <table> <thead> <tr>{this.getHeader()}</tr> </thead> <tbody> {this.getRowsData()} </tbody> </table> </div> ); } }
方案2:扁平化嵌套字段为独立列
将嵌套字段展开为单独的列(比如address.street、address.geo.lat),完整展示所有字段:
// 递归提取所有嵌套字段的路径 const getFlattenKeys = (obj, parentPath = '') => { return Object.keys(obj).reduce((keys, key) => { const fullPath = parentPath ? `${parentPath}.${key}` : key; const value = obj[key]; if (typeof value === 'object' && value !== null && !Array.isArray(value)) { return [...keys, ...getFlattenKeys(value, fullPath)]; } return [...keys, fullPath]; }, []); } // 根据路径获取嵌套值 const getValueByPath = (obj, path) => { return path.split('.').reduce((current, key) => current?.[key], obj); } const RenderRow = (props) => { return props.flattenKeys.map((path, index) => { return <td key={`${path}_${index}`}>{getValueByPath(props.data, path)}</td>; }) } export default class Table extends React.Component { constructor(props){ super(props); this.getHeader = this.getHeader.bind(this); this.getRowsData = this.getRowsData.bind(this); this.getFlattenKeys = this.getFlattenKeys.bind(this); } getFlattenKeys = function(){ return getFlattenKeys(this.props.data[0]); } getHeader = function(){ var keys = this.getFlattenKeys(); return keys.map((key, index)=>{ return <th key={key}>{key.toUpperCase()}</th> }) } getRowsData = function(){ var items = this.props.data; var keys = this.getFlattenKeys(); return items.map((row, index)=>{ return <tr key={index}><RenderRow data={row} flattenKeys={keys}/></tr> }) } render() { return ( <div> <table> <thead> <tr>{this.getHeader()}</tr> </thead> <tbody> {this.getRowsData()} </tbody> </table> </div> ); } }
补充说明
- 方案1适合不需要拆分嵌套字段、整体展示的场景,改动量最小
- 方案2适合需要把所有嵌套字段拆成独立列展示的场景,展示更清晰
内容的提问来源于stack exchange,提问作者CreatoR750
相关产品推荐
相关产品推荐

