React项目中Uncaught TypeError: Cannot read properties of undefined(product)错误排查
问题:Uncaught TypeError: Cannot read properties of undefined (reading 'product')
我遇到了上述错误,打印每个购物车项到控制台后发现部分项结构异常,怀疑是购物车项的类型问题导致,但不清楚为何购物车项之间会存在差异。以下是相关代码及数据结构:
CartSummary 组件
import React, {useEffect} from 'react'; import {Badge, DropdownItem, DropdownMenu, DropdownToggle, Spinner, UncontrolledDropdown} from "reactstrap"; import {useDispatch, useSelector} from "react-redux"; import {cartActions} from "../redux/slice/cartSlice"; import {useNavigate} from "react-router-dom" import alertify from "alertifyjs"; import {fetchCart} from "../redux/thunk/cartActionThunk"; import {PageSpinner} from "./spinner/Spinner"; const CartSummary = () => { const cart = useSelector(state => (state.cartStore.cart)) const isLoading = useSelector(state => (state.uiStore.isLoading)) const dispatch = useDispatch() const handleRemoveFromCart = (product) => { dispatch(cartActions.removeFromCart(product.id)) alertify.error(product.productName + " removed from the cart", 1) } const navigate = useNavigate() useEffect(() => { dispatch(fetchCart()) }, [dispatch]) return ( <div> <UncontrolledDropdown nav inNavbar> <DropdownToggle nav caret> Cart </DropdownToggle> <DropdownMenu> { cart.cartItems.map((item) => { console.log('item', item) // 打印购物车项的位置 return <DropdownItem style={{ justifyContent: "space-between", display: "flex", alignContent: "center", margin: 10 }} key={item.id}> {item.product.productName} <Badge color="success">{item.totalQuantity}</Badge> </DropdownItem> }) } <DropdownItem divider/> <DropdownItem style={{textAlign: "end"}}> <Badge color="success">${cart.totalPrice}</Badge> </DropdownItem> <DropdownItem style={{textAlign: "center"}} onClick={() => navigate("/cart-details")}> Show cart details </DropdownItem> </DropdownMenu> </UncontrolledDropdown> </div> ); }; export default CartSummary;
Cart Action Thunk
import {API_URL} from "../../const/url"; import {cartActions} from "../slice/cartSlice"; import alertify from "alertifyjs"; import {uiActions} from "../slice/uiSlice"; export const addToCart = (product) => { const productDto = { "id": product.id, "productName": product.productName, "quantityPerUnit": product.quantityPerUnit, "unitPrice": product.unitPrice, "unitsInStock": product.unitsInStock, "categoryId": product.category.id } const userId = 1; return (dispatch) => { dispatch(uiActions.setIsLoading(true)) fetch(API_URL + '/cartItem?userId=' + userId, { method: 'POST', headers: {"Content-Type": "application/json"}, body: JSON.stringify(productDto) } ).then((response) => { if (!response.ok) { throw Error("Couldn't add " + productDto.productName + " to the cart.") } return response.json() }).then((result) => { dispatch(cartActions.addProduct(result)) dispatch(uiActions.setIsLoading(false)) alertify.success(productDto.productName + " added successfully.") }).catch((err) => { dispatch(uiActions.setError(err)) dispatch(uiActions.setIsLoading(false)) alertify.error(err.message) }) } } export const fetchCart = () => { const userId = 1; return (dispatch)=>{ dispatch(uiActions.setIsLoading(true)) fetch(API_URL + '/cartItem?userId=' + userId, { method: 'GET' }).then((response)=>{ if(!response.ok){ throw Error("Couldn't fetch cart data") } return response.json() }).then((result)=>{ dispatch(cartActions.fetchCart(result)) dispatch(uiActions.setIsLoading(false)) }).catch((err)=>{ dispatch(uiActions.setError(err)) dispatch(uiActions.setIsLoading(false)) alertify.error(err.message) }) } } export const removeFromCart = (product) => { return (dispatch) => { fetch(API_URL + '/') } }
预期的Cart JSON结构
{ "id": 1, "cartItems": [ { "id": 22, "totalQuantity": 1, "totalPrice": 37.0, "product": { "id": 6, "productName": "Queso Manchego La Pastora", "quantityPerUnit": "10 - 500 g pkgs.", "unitPrice": 37.0, "unitsInStock": 86, "categoryId": 6 } } ], "totalQuantity": 1, "totalPrice": 37.0 }
解决方法
添加防御性检查
直接访问item.product.productName前先判断字段是否存在,避免报错:{cart.cartItems.map((item) => { console.log('item', item) // 跳过结构异常的项 if (!item?.product) return null; return <DropdownItem style={{ justifyContent: "space-between", display: "flex", alignContent: "center", margin: 10 }} key={item.id}> {item.product.productName} <Badge color="success">{item.totalQuantity}</Badge> </DropdownItem> })}排查数据异常根源
- 检查后端
/cartItem接口返回数据,确认是否存在无product字段的购物车项,可能是后端关联查询逻辑错误。 - 查看Redux的
cartSlice中fetchCartreducer的处理逻辑,确认是否正确解析了返回的结构。 - 验证
addToCart接口的返回结果,确保新增的购物车项包含完整的product结构。
- 检查后端
规范初始状态
在Redux的cart初始状态中,给cartItems设置空数组默认值,确保组件渲染时不会因为状态未初始化出现结构错误。
内容的提问来源于stack exchange,提问作者Demir
相关产品推荐
相关产品推荐

