React中使用.map()渲染数组数据失败求助
问题分析与修复方案
你的代码存在多个关键问题,导致.map()无法正常渲染数据,下面逐个说明并给出修复方案:
1. 直接修改State数组,未触发组件重渲染
React的状态不能通过push直接修改,必须使用setEquipment更新状态,否则组件无法感知数据变化。
原错误代码:
equipment.push({ value: item, date: item.Dato, status: item.Status, start: item.StartLocation, end: item.EndLocation, col: item.Collateral, reward: item.Reward });
修复方式:生成新数组后更新状态
const newEquipment = snapshot.map(item => ({ value: item, date: item.Dato, status: item.Status, start: item.StartLocation, end: item.EndLocation, col: item.Collateral, reward: item.Reward })); setEquipment(newEquipment);
2. 未执行渲染函数
在return语句中你仅引用了renderItems函数,没有调用它,必须改为{renderItems()}才会触发渲染逻辑。
3. 函数组件错误使用this.setState
函数组件没有this上下文,需要先定义对应状态,再用状态更新函数操作:
// 先添加状态定义 const [selectedEquipment, setSelectedEquipment] = useState(null); // 修改handleClick函数 const handleClick = (e) => { let target = e.target; let selectedEquipmentIndex = target.parentElement.getAttribute("data-id"); // 注意属性名是data-id而非dataset-id setSelectedEquipment(selectedEquipmentIndex); };
4. 无效的setTimeout写法
setTimeout(10000)不会产生延迟效果,正确写法是setTimeout(() => {}, 10000),但此处无需延迟,直接删除即可避免阻塞状态更新。
5. 非法HTML标签与无效Key值
<id>不是合法HTML标签,建议改为<div>;同时key={element}用对象作为Key无效,需使用唯一标识(如数据中的Username字段):
return ( <div className="row" key={element.value.Username} data-id={element.value.Username} onClick={handleClick}> // ... 内容 </div> );
6. 初始isLoaded状态错误
初始isLoaded设为true会跳过加载状态显示,应初始化为false:
const [isLoaded, setLoaded] = useState(false);
修复后的完整代码
import { useState, useEffect } from 'react'; function Contracts(props) { const [isLoaded, setLoaded] = useState(false); const [error, setError] = useState(null); const [equipment, setEquipment] = useState([]); const [selectedEquipment, setSelectedEquipment] = useState(null); useEffect(() => { const getContracts = async () => { try { let snapshot = await db.getAllContracts(); if (snapshot) { const newEquipment = snapshot.map(item => ({ value: item, date: item.Dato, status: item.Status, start: item.StartLocation, end: item.EndLocation, col: item.Collateral, reward: item.Reward })); setEquipment(newEquipment); setError(null); } else { throw new Error('未获取到数据'); } } catch (err) { setError(err); } finally { setLoaded(true); } }; getContracts(); }, []); const handleClick = (e) => { let target = e.target; let selectedEquipmentIndex = target.parentElement.getAttribute("data-id"); setSelectedEquipment(selectedEquipmentIndex); }; const renderItems = () => { return ( <div> {equipment.map(element => ( <div className="row" key={element.value.Username} data-id={element.value.Username} onClick={handleClick}> <p className="date">{new Date(element.date).toString()}</p> <p className="status">{element.status}</p> <p className="start">{element.start}</p> <p className="end">{element.end}</p> <p className="col">{element.col}</p> <p className="reward">{element.reward}</p> </div> ))} </div> ); }; if (error) { return <div>Error: {error.message}</div>; } else if (!isLoaded) { return <div>Loading...</div>; } else { return ( <article id="header"> <article id="content"> <section className="container"> <div className="header"><h1></h1></div> <div className="titleArea"> <div className="eqnavn"><h1>Date: </h1></div> <div className="eqstatus"><h1>Status: </h1></div> <div className="eqstart"><h1>Start: </h1></div> <div className="eqend"><h1>End: </h1></div> <div className="eqcol"><h1>Collateral: </h1></div> <div className="eqreward"><h1>Reward: </h1></div> </div> {renderItems()} </section> </article> </article> ); } } export default Contracts;
额外注意事项
- 确认数据库返回的字段名与代码匹配(如数据中日期字段是
date而非Dato,需修改为date: item.date) - 时间戳格式的日期可通过
new Date(element.date).toString()转为可读性更强的格式
内容的提问来源于stack exchange,提问作者Selena
相关产品推荐
相关产品推荐

