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

React项目中无法渲染API请求数据的问题求助

解决React中TypeError: Cannot read properties of undefined (reading map)问题

错误原因分析

  1. 初始值未定义:你声明的posts是普通变量,初始值为undefined,组件首次渲染时执行posts.map会直接报错——undefined不存在map方法。
  2. 普通变量无法触发重渲染:即便在useEffect中给posts赋值,普通变量的变化不会触发React组件重新渲染,页面永远拿不到更新后的数据。
  3. 日期格式存在bug:getMonth()返回0-11(对应1-12月),直接拼接"0"+month会导致10-12月变成010/011/012,不符合API要求的日期格式;两位数日期(如10号)也会出现类似拼接错误。
  4. 数据边界未处理:如果API返回的文章不足20条,循环i<20会导致data[i]为undefined,引发新的报错。
  5. 直接操作DOM不符合React范式:用document.querySelector控制loading显示,不如用React状态管理更合理。

解决方案

  1. 用useState声明posts,初始值设为空数组,确保首次渲染时posts是可遍历的数组。
  2. 用setPosts更新状态,触发组件重渲染以展示新数据。
  3. 修复日期格式,用padStart补零,同时注意月份要+1(getMonth()从0开始计数)。
  4. 限制循环次数为API返回数据长度与20的最小值,避免数组越界。
  5. 用状态控制loading的显示/隐藏,替代直接操作DOM。

修改后的News组件代码

import React, { useEffect, useState } from "react";
import SyncIcon from "@mui/icons-material/Sync";
import axios from "axios";
import "../css/news.css";
import Post from "./Post";

function News() {
  // 用useState声明状态,初始值为空数组
  const [posts, setPosts] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    async function loadPosts() {
      const date = new Date();
      const day = String(date.getDate()).padStart(2, '0');
      // 月份+1后补零,适配API日期格式
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const year = date.getFullYear();
      const fullDate = `${year}-${month}-${day}`;

      try {
        const request = await axios.get(
          `https://newsapi.org/v2/everything?qInTitle=Ukraine&from=${fullDate}&sortBy=publishedAt&apiKey=363858d3a88f49ffad9b467282270c8a`
        );

        const data = request.data.articles;
        const response = [];
        // 取数据长度和20的最小值,避免越界
        const maxPosts = Math.min(20, data.length);
        for (let i = 0; i < maxPosts; i++) {
          response.push({
            source: {
              name: data[i].source.name,
              url: data[i].url,
            },
            content: {
              title: data[i].title,
              text: data[i].content,
            },
          });
        }
        setPosts(response);
      } catch (err) {
        // 打印具体错误信息,方便排查
        console.error("数据请求失败:", err);
      } finally {
        // 请求完成后无论成功失败都隐藏loading
        setIsLoading(false);
      }
    }

    loadPosts();
  }, []);

  return (
    <section className="news-container">
      <div className="news-posts">
        {/* 用状态控制loading的显示 */}
        {isLoading && (
          <div className="loading">
            <SyncIcon />
          </div>
        )}
        {/* posts为数组,不会触发map报错 */}
        {posts.map((post, index) => (
          {/* 列表渲染必须添加唯一key属性 */}
          <Post
            key={index}
            name={post.source.name}
            url={post.source.url}
            text={post.content.text}
            title={post.content.title}
          />
        ))}
      </div>
    </section>
  );
}

export default News;

额外提示

  • Post组件代码无问题,可继续使用。
  • React列表渲染时,key属性尽量使用数据中唯一标识(如文章的url),而非临时用index。
  • 错误捕获时打印具体错误信息,能更快定位问题。

内容的提问来源于stack exchange,提问作者Roman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:21:02