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

React获取API数据报错Uncaught TypeError: products.map is not a function

报错原因

Uncaught TypeError: products.map is not a function 触发的唯一原因是:调用.map()方法时,products不是数组类型。
对比两份代码就能定位到具体问题:

  • 你写的原生JS逻辑里,接口返回的是单个对象,不是数组:原生代码中拿到响应后直接读取data.product.name、data.product.reviews.rating,没有做任何遍历操作,说明接口实际返回结构是单对象格式,和你React代码里预期的「产品列表数组」完全不匹配。
  • React代码中你给products设置的初始值是空数组,请求成功后直接把整个response.data(也就是那个单对象)赋值给了products,JS对象本身没有.map方法,渲染时直接触发报错。
  • 额外问题:你写的遍历逻辑也和数据结构不匹配,如果products真的是产品数组,遍历取数时应该直接访问数组元素的对应属性,不需要多套一层data.product;另外列表遍历没有加必填的key属性,后续也会触发React警告。
修复方案

根据接口实际返回结构二选一即可:

场景1:接口确实返回单个产品对象

这种情况不需要用数组存数据,直接把state初始值设为null,渲染前做好判空、加载态、错误态处理即可:

import { useState, useEffect } from "react";
import axios from "axios";

function DataFetching() {
  // 单对象场景初始值设为null,不要误用空数组
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  useEffect(() => {
    const loadProduct = async () => {
      try {
        const response = await axios.get("https://CENSORED/");
        setProduct(response.data);
      } catch (err) {
        setError("数据拉取失败,请稍后重试");
      } finally {
        setLoading(false);
      }
    };
    loadProduct();
  }, []);

  if (loading) return <div>加载中...</div>;
  if (error) return <div>{error}</div>;
  if (!product) return null;

  return (
    <div className="App">
      <h4>{product.product.name}</h4>
      <p>评分:{product.product.reviews.rating}</p>
    </div>
  );
}

场景2:接口预期返回产品列表数组

这种情况说明你取错了响应字段:axios拿到的response.data是整个响应体,数组大概率嵌套在response.data的某个属性下(比如常见的response.data.list、response.data.products),你需要先打印response.data确认实际结构,取到正确的数组字段再赋值给state,示例代码如下:

import { useState, useEffect } from "react";
import axios from "axios";

function DataFetching() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  useEffect(() => {
    const loadProducts = async () => {
      try {
        const response = await axios.get("https://CENSORED/");
        // 替换成你实际接口里数组所在的字段路径
        const productList = response.data.products;
        // 加一层类型校验,避免接口异常返回非数组内容触发报错
        setProducts(Array.isArray(productList) ? productList : []);
      } catch (err) {
        setError("数据拉取失败,请稍后重试");
      } finally {
        setLoading(false);
      }
    };
    loadProducts();
  }, []);

  if (loading) return <div>加载中...</div>;
  if (error) return <div>{error}</div>;

  return (
    <div className="App">
      {products.map((item) => (
        // 列表项必须加唯一key,替换成你数据里的实际唯一标识,比如id
        <div key={item.id}>
          <h4>{item.product.name}</h4>
          <p>评分:{item.product.reviews.rating}</p>
        </div>
      ))}
    </div>
  );
}

调试提示:如果不确定接口返回结构,直接在请求成功回调里打印console.log(response.data),看清楚实际数据格式再写渲染逻辑,不要靠猜写代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:27:18