React JS中循环遍历数组渲染表格时触发控制台报错
问题背景
需要遍历App.js中的expenses数组,以表格形式在浏览器中输出数组内容。
已编写代码
App.js return 片段
return ( <div className="container"> <h1> Expenses </h1> <table className="table table-bordered"> <tr> <th>Title</th> <th>Amount</th> <th>Date</th> </tr> {expenses.map((expense, index) => ( <tr data-index={index}> <td>{expense.title}</td> <td>{expense.amount}</td> <td>{expense.date}</td> </tr> ))} </table> </div> );
ExpenseItem 组件代码
import './ExpenseItem.css'; function ExpenseItem(props) { return ( <div className="expense-item" > <div>{props.date.toISOString()}</div> <div className="expense-item__description"> <h2>{props.title}</h2> <div className="expense-item__price">{props.amount}</div> </div> </div> ) } export default ExpenseItem
代码运行后控制台抛出报错:
报错原因
- 列表渲染未加唯一
key属性:React对map生成的同级列表元素要求必须传入唯一key值用于虚拟DOM对比,缺失会直接抛出警告,特殊场景下会导致渲染错位。 - 日期类型兼容缺失:如果expenses数组内的date字段是字符串而非Date实例,直接调用
toISOString()方法会触发「xxx.toISOString is not a function」的类型错误;如果date是Date实例,直接在td标签中渲染会输出完整的时间对象转字符串结果,格式冗余不符合展示需求。 - 代码冗余且结构不符合规范:已编写的ExpenseItem组件未在表格渲染逻辑中使用,且组件根元素为div,无法直接作为表格行嵌入table结构,会导致HTML解析异常。
修复方案
方案1:直接修正表格渲染逻辑(不使用ExpenseItem组件)
补全table标签的thead、tbody语义化结构,给列表行加key,统一日期格式化逻辑:
return ( <div className="container"> <h1>Expenses</h1> <table className="table table-bordered"> <thead> <tr> <th>Title</th> <th>Amount</th> <th>Date</th> </tr> </thead> <tbody> {expenses.map((expense, index) => { // 兼容字符串/Date对象两种日期格式 const date = expense.date instanceof Date ? expense.date : new Date(expense.date); return ( // 优先用数据自带的唯一id作为key,无id时用index兜底 <tr key={expense.id ?? index}> <td>{expense.title}</td> <td>{expense.amount}</td> <td>{date.toLocaleDateString()}</td> </tr> ) })} </tbody> </table> </div> );
方案2:改造ExpenseItem组件适配表格场景
调整组件根元素为tr,增加日期类型兼容处理,避免类型错误:
import './ExpenseItem.css'; function ExpenseItem(props) { // 兼容传入字符串格式日期的场景 const targetDate = props.date instanceof Date ? props.date : new Date(props.date); return ( <tr className="expense-item"> <td>{targetDate.toLocaleDateString()}</td> <td className="expense-item__description"> {props.title} </td> <td className="expense-item__price">{props.amount}</td> </tr> ) } export default ExpenseItem
改造后App.js中tbody内的渲染逻辑可直接替换为组件调用:
{expenses.map((expense, index) => ( <ExpenseItem key={expense.id ?? index} title={expense.title} amount={expense.amount} date={expense.date} /> ))}
内容的提问来源于stack exchange,提问作者Philippe Mallari
相关产品推荐
相关产品推荐

