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

购物车添加商品报Cannot read properties of null (reading 'product')错误

购物车添加商品报错:Unhandled Rejection (TypeError): Cannot read properties of null (reading 'product')

问题根因

报错本质是代码尝试读取null值的product属性,问题不在你怀疑的商品重复判断逻辑,核心诱因有3个:

  • Redux初始化cart模块state时,直接读取localStorage缓存未做校验。如果缓存值为null、非数组格式、数组内存在空元素,后续reducer遍历cartItems时碰到null值就会触发属性读取错误。
  • addToCart方法未加异常捕获,接口请求失败、返回数据格式异常时会直接抛出未处理的Promise拒绝;且原逻辑在dispatch后立刻读取state存缓存,没有做可选链兜底,极端场景会拿到异常值。
  • 文件名/导入路径、路由参数名不匹配也会触发该类错误:比如你贴的reducer文件名为cardReducers.js(多了个d,正确应为cartReducers.js),如果store里导入路径写错会导致cart state为undefined;如果路由参数名和useParams解构的名称不一致,会拿到undefined的商品id,触发无效接口请求。

修复步骤

1. 给store初始化逻辑加缓存校验

找到Redux store配置文件(通常为store.js),修改localStorage读取逻辑,确保初始cartItems始终为合法有效数组:

// 读取缓存时做空值兜底
const cartCache = localStorage.getItem('cartItems')
let cartItemsFromStorage = []
if (cartCache) {
  try {
    const parsed = JSON.parse(cartCache)
    // 校验格式,过滤数组内无效空值
    cartItemsFromStorage = Array.isArray(parsed) ? parsed.filter(item => item?.product) : []
  } catch (e) {
    // JSON解析失败时重置为空数组
    cartItemsFromStorage = []
  }
}

const initialState = {
  cart: { cartItems: cartItemsFromStorage }
}

2. 修复cartReducer逻辑,确认导入路径正确

首先修正reducer文件名为cartReducers.js,确认store中导入路径和文件名完全匹配,再修改reducer逻辑增加遍历容错:

import { CART_ADD_ITEM } from "../constants/cartConstants"

export const cartReducer = (state = { cartItems: [] }, action) => {
    switch (action.type) {
        case CART_ADD_ITEM:
            const item = action.payload
            // 先过滤无效空值再做重复判断
            const validCartItems = state.cartItems.filter(x => x?.product)
            const existItem = validCartItems.find(x => x.product === item.product)

            if(existItem){
                return{
                    ...state,
                    cartItems: validCartItems.map(x =>
                        x.product === existItem.product ? item : x)
                }
            }else{
                return{
                    ...state,
                    cartItems:[...validCartItems, item]
                }
            }
        
        default:
            return state
    }
}

3. 重构addToCart action,增加错误捕获

修改cartActions.js,增加参数校验、请求错误捕获、state读取兜底:

import axios from 'axios' 
import { CART_ADD_ITEM } from '../constants/cartConstants';

export const addToCart = (id, qty) => async (dispatch, getState) => {
    try {
        // 拦截无效商品id
        if (!id) return
        const { data } = await axios.get(`/api/products/${id}`)
        // 校验接口返回数据合法性
        if (!data?._id) throw new Error('商品信息获取失败')

        dispatch({
            type: CART_ADD_ITEM,
            payload: {
                product: data._id, 
                name: data.name,
                image: data.image,
                price: data.price,
                countInStock: data.countInStock, 
                qty
            }
        })
        // 读取最新state时加可选链兜底
        const latestCartItems = getState().cart?.cartItems || []
        localStorage.setItem('cartItems', JSON.stringify(latestCartItems))
    } catch (err) {
        console.error('加入购物车失败:', err.message)
        // 可按需增加错误提示dispatch逻辑
    }
}   

4. 校验路由参数匹配性

检查路由配置文件,如果购物车路由的参数名为:id,需要修改CartScreen.js中的useParams解构逻辑,保证参数名一致:

// 路由参数为:id时,做别名映射即可,不用改后续逻辑
const { id: prodId } = useParams()

改完后清空localStorage里的旧cartItems缓存,刷新页面重新测试即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 00:01:18