当我将产品添加到购物车时,它的数量=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;
请提供解决方案
关于此评论,问题在于
useEffect
运行了错误的逻辑。在购物车元素中,它应该只读取 cartItems
状态并显示它们。因为购物车项目状态突变应该通过添加或删除等操作来完成,而不是像这样对安装产生副作用。
您应该添加另一个操作
updateCartItemsFromCache()
,它不带参数,只需通过缓存覆盖状态并在购物车组件的 useEffect
中调用它。
对于这种类型的缓存,我强烈建议您使用
redux-persist
。这将编写缓存函数以确保您的本地存储和状态始终同步。尽管该包已停止维护,但它仍然足够稳定,可以在生产中使用。他们还承诺很快会实施新的替代方案。
编码愉快!