当我进入购物车页面时,商品数量自动增加两倍

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

当我将产品添加到购物车时,它的数量=2,当我返回并再次进入我的购物车页面时,数量变为 4,并且总是以 2 增加。

这是我的 addProduct() 函数。

import axios from "axios";
import React, { useEffect, useState } from "react";
import { NavLink, useParams } from "react-router-dom";
import { useDispatch } from "react-redux";
import { addToCart } from "../Redux/action/action";
import { useSelector } from "react-redux";

import { FaStar } from "react-icons/fa";
import Skeleton from "react-loading-skeleton";

const ProductDetails = () => {
  const { id } = useParams();
  const cartItems = useSelector((state) => state.handleCart);
  const [isLoading, setIsLoading] = useState(true);
  const [product, setProduct] = useState([]);

  const dispatch = useDispatch();

  useEffect(() => {
    const fetchProduct = async () => {
      try {
        setIsLoading(true);
        const { data } = await axios.get(
          `https://fakestoreapi.com/products/${id}`
        );
        setProduct(data);
        setIsLoading(false);
      } catch (error) {
        console.error("Error fetching product:", error);
      } finally {
        setIsLoading(false);
      }
    };

    fetchProduct();
  }, [id]);

  const addProduct = (product) => {
    if (product) {
      dispatch(addToCart(product));

      // Retrieve existing cart items from localStorage
      const existingCartItemsJSON = localStorage.getItem("CartItems");
      const existingCartItems = existingCartItemsJSON
        ? JSON.parse(existingCartItemsJSON)
        : [];

      // Ensure that existingCartItems is an array
      if (!Array.isArray(existingCartItems)) {
        console.error("Invalid existingCartItems:", existingCartItems);
        return;
      }

      // Add the new product to the existing cart items
      const updatedCartItems = [...existingCartItems, product];

      // Store the updated cart items back in localStorage

      localStorage.setItem("CartItems", JSON.stringify(updatedCartItems));
    } else {
      console.error("Invalid product:", product);
    }
  };

  useEffect(() => {
    const cartJSON = localStorage.getItem("CartItems");
    if (cartJSON) {
      const cartArray = JSON.parse(cartJSON);

      // Ensure cartArray is always an array
      if (!Array.isArray(cartArray)) {
        console.error("Invalid cartArray:", cartArray);
        return;
      }
      //Dispatch addToCart action to populate the Redux store with items from local storage
      cartArray.forEach((item) => {
        dispatch(addToCart(item));
      });
    }
  }, [dispatch]);

  const ShowProducts = () => (
    <div className="d-flex row" key={product.id}>
      <div className="col-md-6 col-sm-3 mt-5">
        <img
          src={product.image}
          alt={product.title}
          height="400px"
          width="400px"
        />
      </div>
      <div className="col-md-6 mt-5">
        <h4 className="text-uppercase text-black-50">{product.category}</h4>
        <h1 className="display-5">{product.title}</h1>
        <p className="lead fw-bolder">
          Rating {product.rating && product.rating.rate}
          <FaStar />
        </p>
        <h3 className="display-6 fw-bolder my-4">${product.price}</h3>
        <p className="lead">{product.description}</p>
        <button className="btn btn-primary" onClick={() => addProduct(product)}>
          Add to Cart
        </button>
        <NavLink to="/MyCart" className="btn btn-outline-dark ms-2">
          Go to Cart
        </NavLink>
      </div>
    </div>
  );

  return (
    <>
      <div className="container py-5">
        <div className="row">
          {isLoading ? (
            <>
              {" "}
              <div className="col-md-6">
                <Skeleton height={400} />
              </div>
              <div className="col-md-6">
                <Skeleton width={300} height={50} />
                <Skeleton height={75} />
                <Skeleton width={25} height={150} />
                <Skeleton height={50} />
                <Skeleton height={150} />
                <Skeleton height={50} width={100} />
                <Skeleton height={50} width={100} />
              </div>
            </>
          ) : (
            product && <ShowProducts />
          )}
        </div>
      </div>
    </>
  );
};

export default ProductDetails;

在这里,我从本地存储中删除数据购买,单击“删除数据”从本地存储中删除,但在我的购物车页面中它仍然存在,因为它的数量= 2

import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { removeFromCart, addToCart } from "../Redux/action/action";
import { NavLink } from "react-router-dom";

const MyCart = () => {
  const cartItem = useSelector((state) => state.handleCart);
  const dispatch = useDispatch();

  useEffect(() => {
    const cartJSON = localStorage.getItem("CartItems");
    if (cartJSON) {
      const cartArray = JSON.parse(cartJSON);
      // Ensure cartArray is always an array
      if (!Array.isArray(cartArray)) {
        console.error("Invalid cartArray:", cartArray);
        return;
      }
      //Dispatch addToCart action to populate the Redux store with items from local storage
      cartArray.forEach((item) => {
        dispatch(addToCart(item));
      });
    }
  }, [dispatch]);

  const handleClose = (item) => {
    dispatch(removeFromCart(item));
    // Remove the item from local storage as well
    const existingCartItemsJSON = localStorage.getItem("CartItems");
    const existingCartItems = existingCartItemsJSON
      ? JSON.parse(existingCartItemsJSON)
      : [];

    const updatedCartItems = existingCartItems.filter(
      (cartItem) => cartItem.id !== item.id
    );

    localStorage.setItem("CartItems", JSON.stringify(updatedCartItems));
  };

  const cartItems = (item) => {
    return (
      <div className="px-4 my-5 bg-light rounded-3" key={item.id}>
        <div className="container py-4">
          <button
            className="btn-close float-end"
            aria-label="Close"
            onClick={() => handleClose(item)}
          ></button>

          <div className="d-flex row justify-content-center">
            <div className="col-md-4">
              <img
                src={item.image}
                alt={item.title}
                height="200px"
                width="180px"
              />
            </div>
            <div className="col-md-4 ">
              <h3> {item.title} </h3>
              <p className="lead"> {item.description} </p>
              <p className="lead fw-bolder">${item.price}</p>
              <p>{item.qty}</p>
            </div>
          </div>
        </div>
      </div>
    );
  };

  const emptyCart = () => {
    return (
      <div className="my-4 px-3 bg-light rounded-3 ">
        <div className="container py-4 ">
          <div className="row">
            <h3>Your Cart is Empty</h3>
          </div>
        </div>
      </div>
    );
  };

  const checkoutButton = () => {
    return (
      <div className="container ">
        <div className="row">
          <NavLink
            to="/checkout"
            className="btn mb-5 btn-outline-primary w-25 mx-auto"
          >
            Checkout
          </NavLink>
        </div>
      </div>
    );
  };

  return (
    <>
      {cartItem.length === 0 && emptyCart()}

      {cartItem.length !== 0 && cartItem.map(cartItems)}
      {cartItem.length !== 0 && checkoutButton()}
    </>
  );
};

export default MyCart;

这是我的Reducer.js 函数。 在这里,如果在 ADD_TO_CART 情况下购物车中已存在该商品,则将其数量增加 1;如果在 REMOVE_FROM_CART 情况下数量大于 1,则将数量减少 1

import { ADD_TO_CART, REMOVE_FROM_CART } from "../action/action-type";

const cart = [];

const handleCart = (state = cart, action) => {
  const product = action.payload;

  switch (action.type) {
    case ADD_TO_CART:
      const existingProduct = state.find((item) => item.id === product.id);

      if (existingProduct) {
        return state.map((item) =>
          item.id === product.id ? { ...item, qty: item.qty + 1 } : item
        );
      } else {
        const product = action.payload;
        return [
          ...state,

          {
            ...product,
            qty: 1,
          },
        ];
      }

    case REMOVE_FROM_CART:
      const existingProductToRemove = state.find(
        (item) => item.id === product.id
      );
      if (existingProductToRemove.qty === 1) {
        // Remove the item from the state
        const newState = state.filter((item) => item.id !== product.id);
        // Store the updated cart state in local storage
        localStorage.setItem("CartItems", JSON.stringify(newState));
        return newState;
      } else {
        // Decrease the quantity of the item in the state
        const newState = state.map((item) =>
          item.id === product.id ? { ...item, qty: item.qty - 1 } : item
        );
        // Store the updated cart state in local storage
        localStorage.setItem("CartItems", JSON.stringify(newState));
        return newState;
      }

    default:
      return state;
  }
};

export default handleCart;

请提供解决方案

javascript reactjs e-commerce
1个回答
0
投票

关于此评论,问题在于

useEffect
运行了错误的逻辑。在购物车元素中,它应该只读取
cartItems
状态并显示它们。因为购物车项目状态突变应该通过添加或删除等操作来完成,而不是像这样对安装产生副作用。

您应该添加另一个操作

updateCartItemsFromCache()
,它不带参数,只需通过缓存覆盖状态并在购物车组件的
useEffect
中调用它。

对于这种类型的缓存,我强烈建议您使用

redux-persist
。这将编写缓存函数以确保您的本地存储和状态始终同步。尽管该包已停止维护,但它仍然足够稳定,可以在生产中使用。他们还承诺很快会实施新的替代方案。

编码愉快!

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