English 中文(简体)
当我进入汽车页时,物品数量自动增加两倍
原标题:Quantity of item increases twice automatically when i entered my cart page

当加油产品时,其数量为2,而如果再回头并再次上我一页,那么该数量就会达到4个,每增加2个。

这里是我的补充职能。

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;

Here is my Reducer.js function. Here i increasing the quantity of an item by 1 if it is already present in the cart in ADD_TO_CART case and decreasing the quantity by 1 when the quantity is greater than 1 in REMOVE_FROM_CART case

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;

请提供解决办法。

问题回答

Regarding the conversation in this post, the problem is the useEffect was running the wrong logic. In the cart element, it should ONLY READ the cartItems state and display them. Because cart items state mutation should be done through actions like adding or removing, not in a side effect on mount like this.

您应增加另一项行动:updateCartItemsFromCache(,其中不包含任何内容,而只是ache超越国家,而是将其称作Cart构成部分的use Effect

对于这种藏匿点,我高度建议您使用<条码>代号---persist。 这将写明切身功能,确保你们的地方储存,你们的国家总是会合。 尽管一揽子计划被切断了维修,但保持稳定,在生产中使用。 他们还承诺很快将实施新的备选办法。

Hapy coding!





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签