React运行报错Uncaught TypeError: product.map is not a function求助
React 运行时报错
product.map is not a function 排查与修复 问题现象
- 搭建React练习项目时触发运行时报错:
Item.js:12 Uncaught TypeError: product.map is not a function,报错位置为Item组件第12行 - 实现逻辑:通过fetch请求拉取商品接口数据,经
ItemListContainer->ItemList->Item三层组件逐层传递props,最终在Item组件渲染商品详情
问题根因
一共存在4处逻辑/语法问题,核心报错由前2个问题直接引发:
- 核心原因1:
map是数组专属方法,仅能遍历数组类型数据。Item组件接收到的product是ItemList遍历后传入的单个商品对象,本身不是数组,根本不需要调用map遍历,直接访问属性即可。 - 核心原因2:Item组件内的useEffect逻辑错误,
setSellProduct({product})会把传入的单个商品对象包装成{product: 商品对象}的嵌套普通对象,普通对象不存在map方法,直接触发类型错误。 - 冗余渲染问题:ItemListContainer中已经对商品数组
swSell做了map遍历,但每次遍历都把整个swSell数组传给ItemList,会导致商品列表重复渲染N次(N为商品总数)。 - 语法/字段匹配问题:Item组件末尾导出语句拼写错误(
expor少写了末尾的t);代码中使用的name/picture字段和fakestoreapi返回的title/image字段不匹配,即使解决报错也无法正常渲染内容;列表遍历未加React要求的唯一key属性。
修复方案
按组件分别修正逻辑即可:
1. 修复Item组件
删除不必要的state、effect和错误的map逻辑,直接渲染单个商品对象,修正导出拼写和字段名:
import React from "react"; import '../App.css'; import 'materialize-css/dist/css/materialize.css'; import Count from './ItemCount'; export const Item = (({product}) => { const mensaje = () => { alert ('Gracias por su compra'); } return ( <Count stock={product.stock} onAdd ={mensaje} > <div id={product.id}> <h3>{product.title}</h3> - <small>{product.category}</small> <img src={product.image} alt="Producto" className="itemImg" /> <p>{product.description}</p> <p>{product.price}</p> </div> </Count> ) }); // 修正导出拼写错误 export default Item;
2. 修复ItemListContainer组件
删除多余的遍历逻辑,仅需把整个商品数组传给ItemList一次即可,避免重复渲染:
import React, { useEffect, useState } from "react"; import '../App.css'; import 'materialize-css/dist/css/materialize.css'; import ItemList from './ItemList'; export const ItemListContainer =() => { const [swSell,setSwSell] = useState([]) useEffect(() => { fetch('https://fakestoreapi.com/products') .then((res) => res.json()) .then((data) => { setSwSell(data); }) .catch((err) => { console.log(err); }); }, []); return( <div className="parent"> <ItemList item={swSell} /> </div> ) } export default ItemListContainer;
3. 优化ItemList组件
修正变量名遮蔽问题(原代码map遍历参数和外层prop同名item,可读性差),给列表项加唯一key属性:
import React from "react"; import '../App.css'; import 'materialize-css/dist/css/materialize.css'; import Item from './Item'; export const ItemList = (({item}) => { return ( <div className="child"> { item.map((product) =>( <Item product={product} key={product.id}/> )) } </div> ) }); export default ItemList;
开发注意点
- 调用遍历方法前先确认数据类型:数组类型才可以用
map/filter等数组方法,单个对象直接访问属性即可,无需遍历 - 组件分层时提前规划遍历逻辑:列表类组件负责遍历数组生成单条子组件,单条内容组件只负责接收单个对象渲染内容,不要跨层重复遍历
- 传值时避免无意义的对象包装,比如
{product}这种写法会额外嵌套一层数据结构,极易引发类型错误 - 对接接口时先确认返回字段名和代码中使用的字段一致,列表遍历必须加唯一key属性,导出/导入语句注意拼写正确
内容的提问来源于stack exchange,提问作者Juan Pablo Grover Pinto
相关产品推荐
相关产品推荐

