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

Angular 14 NGRX Selector编写报错,如何移除单条同ID购物车商品?

问题排查与解决方案

一、Selector报错原因

你写的Selector存在三个核心问题:

  • createSelector语法错误:它的标准用法是先传入输入选择器数组,再传入转换函数,你直接传单个函数不符合API规范。
  • indexOf用法错误:state是Photo对象数组,state.indexOf(id)是在找数组中是否存在等于数字id的元素,而非photo.id === id的对象,永远会返回-1。
  • 额外参数处理错误:要接收id这类额外参数,需要在输入选择器中通过第三个参数获取。

二、正确的Selector实现

如果确实需要获取第一个匹配ID的索引,正确的Selector写法如下:

import { createSelector } from '@reduxjs/toolkit';

export const basketPosition = createSelector(
  // 输入选择器1:获取购物车数组
  (state: Array<Photo>) => state,
  // 输入选择器2:获取传入的id参数
  (_state: Array<Photo>, { id }: { id: number }) => id,
  // 转换函数:计算第一个匹配的索引
  (basket, id) => basket.findIndex(photo => photo.id === id)
);

三、移除单个同ID商品的Reducer实现

其实不需要额外Selector,直接在Reducer里处理更简洁,推荐两种immutable的实现方式:

方案1:findIndex + 数组切片(性能更优)

on(getBasket, (state, { id }) => {
  const targetIndex = state.findIndex(photo => photo.id === id);
  // 没找到对应商品则返回原数组
  if (targetIndex === -1) return state;
  // 拼接新数组,跳过目标索引的元素
  return [...state.slice(0, targetIndex), ...state.slice(targetIndex + 1)];
});

方案2:reduce构建新数组

on(getBasket, (state, { id }) => {
  let hasRemoved = false;
  return state.reduce((newBasket, photo) => {
    // 只移除第一个匹配的商品
    if (photo.id === id && !hasRemoved) {
      hasRemoved = true;
      return newBasket;
    }
    newBasket.push(photo);
    return newBasket;
  }, [] as Photo[]);
});

原代码问题说明

你用的state.filter(photo => photo.id !== id)会过滤掉所有id匹配的元素,所以当购物车中有多个同ID商品时,会全部被移除。上面的两种方案只会移除第一个匹配的商品,符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 21:48:21