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

React购物车为空时点击移除按钮触发TypeError错误的解决方法

解决React购物车空时点击移除按钮崩溃的问题

问题描述

开发React购物车时,商品添加与移除功能正常,但当购物车为空时,点击“Remove From Cart”按钮会导致应用崩溃,抛出错误:

TypeError: Cannot read properties of undefined (reading 'quantity')

错误指向CartProvider组件中removeFromCart函数的if (isItemInCart.quantity === 1)语句。

错误原因

当购物车为空,或者目标商品不在购物车中时,cartItems.find()方法会返回undefined。此时直接访问isItemInCart.quantity,相当于读取undefined的属性,必然触发类型错误。

另外,removeFromCart函数还存在一个次要bug:在map处理时,else分支错误返回了0,这会导致购物车列表混入非商品数据,后续计算总价等逻辑也会出错。

修复步骤

1. 修复removeFromCart核心逻辑

修改CartProvider中的removeFromCart方法,先判断商品是否存在于购物车中,再执行后续逻辑,同时修正map分支的返回值:

const removeFromCart = (item) => {
  const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

  // 商品不在购物车中时直接返回,避免后续报错
  if (!isItemInCart) return;

  if (isItemInCart.quantity === 1) {
    setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
  } else {
    setCartItems(
      cartItems.map((cartItem) =>
        cartItem.id === item.id
          ? { ...cartItem, quantity: cartItem.quantity - 1 }
          : cartItem // 修复:返回原商品对象,而非0
      )
    );
  }
};

2. 优化商品页面的移除按钮(可选)

在Products组件中,根据商品是否在购物车中动态禁用移除按钮,从源头避免无效点击:

// 在Products组件的商品循环中,修改Remove按钮的disabled属性
<Button
  onClick={() => removeFromCart(products)}
  id="RemoveFromCart"
  size="large"
  variant="contained"
  endIcon={<RemoveIcon />}
  // 商品不在购物车时禁用按钮
  disabled={!cartItems.find(item => item.id === products.id)}
>
  Remove From Cart
</Button>

3. 合并localStorage初始化逻辑(可选)

原CartProvider中存在重复的localStorage初始化逻辑,两个useEffect可能导致状态覆盖,建议合并:

// 替换原有的两个useEffect,保留一个初始化+同步逻辑
useEffect(() => {
  const savedCartItems = localStorage.getItem("cartItems");
  if (savedCartItems) {
    setCartItems(JSON.parse(savedCartItems));
  }
}, []);

useEffect(() => {
  localStorage.setItem("cartItems", JSON.stringify(cartItems));
}, [cartItems]);

完整修复后的CartProvider代码

import { createContext, useState, useEffect } from 'react'
import React from 'react'
import products from '../components/product';
export const CartContext = createContext()

export const CartProvider = ({ children }) => {
  const [cartItems, setCartItems] = useState([])

  const addToCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (isItemInCart) {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity + 1 }
            : cartItem
        )
      );
    } else {
      setCartItems([...cartItems, { ...item, quantity: 1 }]);
    }
  };

  const removeFromCart = (item) => {
    const isItemInCart = cartItems.find((cartItem) => cartItem.id === item.id);

    if (!isItemInCart) return;

    if (isItemInCart.quantity === 1) {
      setCartItems(cartItems.filter((cartItem) => cartItem.id !== item.id));
    } else {
      setCartItems(
        cartItems.map((cartItem) =>
          cartItem.id === item.id
            ? { ...cartItem, quantity: cartItem.quantity - 1 }
            : cartItem
        )
      );
    }
  };

  const clearCart = () => {
    setCartItems([]);
  };

  const getCartTotal = () => { 
    return cartItems.reduce((total, cartItem) => total + cartItem.price * cartItem.quantity, 0);
  };

  useEffect(() => {
    const savedCartItems = localStorage.getItem("cartItems");
    if (savedCartItems) {
      setCartItems(JSON.parse(savedCartItems));
    }
  }, []);

  useEffect(() => {
    localStorage.setItem("cartItems", JSON.stringify(cartItems));
  }, [cartItems]);

  return (
    <CartContext.Provider
      value={{
        cartItems,
        addToCart,
        removeFromCart,
        clearCart,
        getCartTotal,
      }}
    >
      {children}
    </CartContext.Provider>
  );
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:42:03