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
相关产品推荐
相关产品推荐

