为什么 Redux 会从购物车中删除所有产品,而不是仅删除我删除的产品?

问题描述 投票:0回答:1

我正在开发一个小型电子商务应用程序,当我在购物车中单击“删除”时,它会删除整个产品,而不仅仅是其中一个产品,请我需要帮助。

我还想知道如何增加和减少产品。我使用了状态钩子,但它增加了购物车中整个产品的数量,而不是仅一种。 感谢您提前的帮助

import { Link } from "react-router-dom";
import "../styles/Cart.css";
import payLogo from "../assets/images/payLogo.png";
import NavBar from "../components/NavBar";
import { MdKeyboardArrowRight } from "react-icons/md";
import { FaStar } from "react-icons/fa";
import { RiDeleteBin6Line } from "react-icons/ri";
import Footer from "../components/Footer";
import BestSellers from "../components/BestSellers";
import { useDispatch, useSelector } from "react-redux";
import { removeFromCart } from "../features/CartState";
import { useState } from "react";

function Cart() {
  const cart = useSelector((state) => state.cart.items);
  const [numItems, setNumItems] = useState(0);
  const dispatch = useDispatch();

  const itemDelete = (item) => {
    dispatch(removeFromCart({ id: item.id }));
  };

  const totalPrice = cart
    .map((item) => item.price)
    .reduce((a, b) => a + b, 0)
    .toFixed(2);
  return (
    <div>
      <NavBar />

      <div className="home-cart">
        <Link to="/">Home</Link>
        <MdKeyboardArrowRight className="arrow-cart" />
        <Link to="/shop">Shop</Link>
        <MdKeyboardArrowRight className="arrow-cart1" />
        <p>Cart</p>
      </div>

      <div className="cart-contain">
        <div className="cart">
          <h4 className="shop-head">Shopping Cart</h4>
          <div className="cart-header">
            <p>Item Details</p>
            <p>Quantity</p>
            <p>Price</p>
          </div>

          <div className="holder">
            {cart.map((item, index) => (
              <div className="cart-item" key={index}>
                <div className="cart-item-details">
                  <div onClick={() => itemDelete(item)} className="image-div">
                    <img src={item.image} alt={item.title} />
                    <h6>
                      <RiDeleteBin6Line /> REMOVE
                    </h6>
                  </div>
                  <div className="cart-item-title">
                    <h3>{item.title}</h3>
                    <p>In Stock</p>
                    <span className="cart-star">
                      <FaStar className="prod-star" />
                      <FaStar className="prod-star" />
                      <FaStar className="prod-star" />
                      <FaStar className="prod-star" />
                      <FaStar className="prod-star" />
                      <h6>28 Reviews</h6>
                    </span>
                  </div>
                </div>

                <div className="item-counter">
                  <button>-</button>
                  <input
                    type="number"
                    name="num"
                    id="num"
                    value={numItems}
                    onChange={(e) => setNumItems(e.target.value)}
                  />
                  <button style={{ background: "#23a6f0", color: "white" }}>
                    +
                  </button>
                </div>

                <div className="item-price">
                  <h4>N{item.price}</h4>
                  <p>{cart.price} x 1 item(s)</p>
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="summary">
          <div className="order-div">
            <h4>Order Summary</h4>
            <p>{cart.length} Items</p>
          </div>
          <div className="delivery">
            <p>Delivery Charges</p>
            <span>
              Add your delivery address to checkout to see delivery charges.
            </span>
          </div>
          <div className="sub-total">
            <p>Subtotal</p>
            <p>&#x20A6; {totalPrice}</p>
          </div>
          <div className="total">
            <h3>Total</h3>
            <h3>&#x20A6; {totalPrice}</h3>
          </div>
          <div className="charges">
            <div>
              <p>Excluding Delivery Charges</p>
            </div>
            <button>Proceed to Checkout</button>
          </div>

          <div className="pay-log">
            <img className="pay-logo" src={payLogo} alt="payment logo" />
          </div>
        </div>
      </div>

      <BestSellers />
      <Footer />
    </div>
  );
}

export default Cart;
/* eslint-disable react-refresh/only-export-components */
import { createSlice } from "@reduxjs/toolkit";

export const cartSlice = createSlice({
  name: "cart",
  initialState: { items: [] },
  reducers: {
    setCart: (state, action) => {
      state.items.push(action.payload);
    },
    removeFromCart: (state, action) => {
      state.items = state.items.filter((item) => item.id !== action.payload.id);
    },
  },
});

export const { setCart, removeFromCart } = cartSlice.actions;
export default cartSlice.reducer;
javascript reactjs react-native redux react-redux
1个回答
0
投票

您的实现看起来是正确的,请尝试再次检查您的逻辑,顺便您可以看看下面的类似实现。

// CART SLICE
import { createSlice } from "@reduxjs/toolkit";

type Item = {
  id: number;
  name: string;
  price: number;
  count: number;
};

const initialState = {
  items: [] as Item[],
};

const cartSlice = createSlice({
  name: "cart",
  initialState,
  reducers: {
    addToCart(state, action) {
      console.log("Adding to cart", action.payload);
      const { id } = action.payload;

      const existingItem = state.items.find((item) => item.id === id);

      if (existingItem) {
        existingItem.count += 1;
      } else {
        state.items.push({ ...action.payload, count: 1 });
      }
    },
    removeFromCart(state, action) {
      console.log(action.payload);

      const id = action.payload.id;
      const existingItem = state.items.find((item) => item.id === id);

      if (existingItem) {
        if (existingItem.count === 1) {
          state.items = state.items.filter((item) => item.id !== id);
        } else {
          existingItem.count -= 1;
        }
      } else {
        console.warn(`Item with id ${id} not found in cart`);
      }
    },
  },
});

export const { addToCart, removeFromCart } = cartSlice.actions;
export default cartSlice.reducer;



// STORE
import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./features/cartSlice";
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";

export const store = configureStore({
  reducer: {
    cart: cartReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;



// USAGE IN THE COMPONENT
import { addToCart, removeFromCart } from "./store/features/cartSlice";
import { useAppDispatch, useAppSelector } from "./store";
import "./App.css";

const products = [
  {
    id: 1,
    name: "Product 1",
    price: 100,
  },
  {
    id: 2,
    name: "Product 2",
    price: 200,
  },
  {
    id: 3,
    name: "Product 3",
    price: 300,
  },
  {
    id: 4,
    name: "Product 4",
    price: 400,
  },
];

function App() {
  const dispatch = useAppDispatch();
  const itemsInCart = useAppSelector((store) => store.cart.items);

  return (
    <div>
      <h1>Cart</h1>

      <p>items in cart:({itemsInCart.length})</p>

      <div className="products">
        {products.map((product) => (
          <div key={product.id}>
            <h3>{product.name}</h3>
            <p>{product.price}</p>
            <button
              onClick={() => {
                dispatch(addToCart(product));
              }}>
              Add to cart
            </button>

            {itemsInCart.find((item) => item.id === product.id) ? (
              <button
                style={{ marginLeft: "10px" }}
                onClick={() => {
                  // dispatch(removeFromCart({ id: product.id })); this works
                  dispatch(removeFromCart(product)); // this also works
                }}>
                Remove from cart
              </button>
            ) : null}
          </div>
        ))}
      </div>
    </div>
  );
}

export default App;

© www.soinside.com 2019 - 2024. All rights reserved.