Angular 18中使用NGRX实现购物车时,添加第二个商品出现Cannot read properties of undefined (reading 'product')错误
Angular 18中使用NGRX实现购物车时,添加第二个商品出现Cannot read properties of undefined (reading 'product')错误
我仔细看了你的代码,很快就定位到了问题的根源:你在分发addToCart action时,参数格式完全不符合要求,而且没有把Gadget正确包装成CartItem类型,再加上reducer里用了太多any类型,导致TypeScript没能提前帮你发现问题,最终在第二次添加商品时触发了运行时错误。
错误的具体原因
- 你的
addToCartaction要求的参数是{ gadget: CartItem },但在AddGadgetComponent里,你直接把Gadget对象传了进去:this.store.dispatch(addToCart(this.gadget)); // 这里传的是Gadget,不是CartItem,也不符合action的参数结构 - 这导致第一次添加的商品,其实是直接把
Gadget对象塞进了购物车(而不是CartItem)。当你第二次添加商品时,reducer遍历购物车列表,尝试访问i.product.id,但此时列表里的第一个条目是Gadget(它没有product属性),所以i.product是undefined,自然就抛出了Cannot read properties of undefined (reading 'product')的错误。
一步步解决问题
1. 修正AddGadgetComponent中的action分发逻辑
你需要把Gadget包装成CartItem类型,并且严格按照action要求的参数结构传递:
import { CartItem } from '../shared/models/cart.item'; import { Gadget } from './gadget.model'; // ... export class AddGadgetComponent implements OnInit { @Input() gadget: Gadget; // 这里指定正确类型,不要用any constructor(private store: Store) { } addGadget() { console.log("Adding gadget to cart", this.gadget.id); // 1. 把Gadget包装成CartItem,默认quantity为1 const cartItem: CartItem = { product: this.gadget, quantity: 1 }; // 2. 按action要求的结构传递参数 this.store.dispatch(addToCart({ gadget: cartItem })); } }
2. 给reducer添加严格的类型定义,去掉any
用具体类型替代any,让TypeScript在开发阶段就帮你检查错误:
import { createReducer, on } from '@ngrx/store'; import { addToCart } from './cart.action'; import { CartState } from './cart.state'; import { CartItem } from '../shared/models/cart.item'; export const initialState: CartState = { cart: [] }; export const cartReducer = createReducer( initialState, on(addToCart, (state: CartState, { gadget }) => { // 现在所有类型都是明确的,不会出现隐性错误 const existingGadget = state.cart.find(item => item.product.id === gadget.product.id); if (existingGadget) { return { ...state, cart: state.cart.map(item => item.product.id === gadget.product.id ? { ...item, quantity: item.quantity + gadget.quantity } : item ) }; } else { return { ...state, cart: [...state.cart, gadget] }; } }) );
3. 可选:给AddGadgetComponent的输入属性指定正确类型
把@Input() gadget: any;改成@Input() gadget: Gadget;,这样TypeScript会帮你确保输入的是正确的Gadget对象。
验证修改后的流程
- 点击「Add To Cart」时,会正确创建
CartItem并分发给action - reducer处理的都是符合
CartItem类型的条目,不会再出现i.product为undefined的情况 - 重复添加同一个商品时,会正确增加数量;添加新商品时,会在购物车中新增条目
内容来源于stack exchange
相关产品推荐
相关产品推荐

