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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 00:15:41