My state is showing an empty cart . Whenever I insert a new product the state’s cartItem[] is empty (ie… not showing the previous items ) , also state.cartItems is an empty array when it is retrieved from useSelector() . Further ,Local storage not working when same item is inserted , The logic work for 2 products and then it will start incrementing the quantity of the last inserted product (not the current one).
I tried everything (from the internet), but this is now the original code . I’ve made this code for storing Items in the local storage because previously it was just replacing the previous items in the localStorage (thus storing only one)
This is the Cart Screen
import React,{useState} from 'react'
import MetaData from '../layout/metaData'
import CartItemCard from '../cart/CartItemCard'
import { motion } from 'framer-motion'
import Footer from '../layout/Footer'
import NoItem from '../layout/noItem.js'
import { useSelector,useDispatch } from 'react-redux'
export default function Cart() {
const dispatch = useDispatch();
const state = useSelector((state)=>state);
console.log(state.cart.cartItems); // this is showing empty array
const [display,setDisplay] = useState('none');
const head = {
product:'Product',
price:'Price',
name:"amarajs",
quantity:1,
}
return (
<>
<MetaData title = "Your Cart" />
<div className = 'container mx-auto my-[16rem] flex flex-col justify-center'>
{/* {!cartItems && <NoItem/>}
<div className = {`flex flex-col justify-center items-center gap-[3.2rem] blur-${display} mb-[5.4rem]`}>
<CartItemCard heading = {head}/>
{cartItems && cartItems.map((item)=>(
<CartItemCard item = {item}/>
))}
</div> */}
<hr className = "p-4 container text-black mb-[3.2rem]"/>
<div className = "px-[5.4rem] sub-total--section flex flex-col items-end self-end mb-[3.2rem]">
<div className = "flex justify-center items-end gap-[1rem]">
<p className = "text-[2.4rem]">
SUBTOTAL
</p>
<p className = "total--price text-[3.2rem] font-semibold">
₹{'1800'}
</p>
</div>
<p className = "total-subhead text-[#555] text-[1.6rem] italic">
Shipping & taxes calculated at checkout
</p>
</div>
<motion.button whileHover= {{scale:1.04}} className = " self-center text-[2.4rem] add-to-cart h-[6.4rem] w-[300px] bg-[rgb(14,14,14)] text-[#fff] rounded-[5rem] hover:bg-[#fff] hover:text-[rgb(14,14,14)] mb-[4.4rem]" >
checkout
</motion.button>
</div>
<Footer/>
</>
)
}
this is cartAction.js
import { ADD_TO_CART } from "../constants/cartConstants";
import axios from "axios";
const setLocalStorage = (...item) =>{
let cartItems = [];
const newItem = item[0][0];
if(localStorage.getItem('cartItems')){
cartItems = JSON.parse(localStorage.getItem('cartItems'));
// if already present -- this is not working for more than 2 products (it will update the quantity of last inserted product instead ,not the current one)
// const alreadyPresent = cartItems.find(i=>i.product===newItem.product);
// if(alreadyPresent){
// cartItems.forEach(x =>{
// if(x.product===newItem.product){
// console.log(x.product,newItem.product)
// x.quantity+=1;
// }else{
// x.quantity = 1;
// }
// })
// }
// else{
cartItems.push(newItem);
// }
}
else{
cartItems.push(newItem)
}
localStorage.setItem('cartItems',JSON.stringify(cartItems));
}
// Add items to cart
export const addItemsToCart = (id,quantity) => async(dispatch,getState) =>{
const {data} = await axios.get(`http://localhost:3000/api/v1/products/${id}`);
// const cartItems = JSON.parse(getState().cart.cartItems);
// console.log(getState().cart)
dispatch({
type: ADD_TO_CART,
payload: {
product: data.product._id,
name: data.product.name,
price: data.product.price,
image: data.product.images[0].url,
stock: data.product.Stock,
quantity,
},
});
setLocalStorage(getState().cart.cartItems);
};
This is CartReducer.js
import { ADD_TO_CART } from "../constants/cartConstants";
export const cartReducer = (state = {cartItems:[]}, action) => {
switch (action.type) {
case ADD_TO_CART:
const item = action.payload
const existItem = state.cartItems.find(x => x.product === item.product)
if(existItem){
console.log("already",state.cartItems)
return{
...state,
cartItems: state.cartItems.map(x =>
x.product === existItem.product ? item : x)
}
}else{
console.log(state.cartItems);
return{
...state,
cartItems:[...state.cartItems, item]
}
}
default:
return state
}
}
2
Answers
It seems like there might be an issue with how you are handling the local storage and updating the Redux state in your addItemsToCart action.
1. Local Storage Handling:
In your setLocalStorage function, you are directly pushing the new item to cartItems. However, for the case where the item already exists, you are commenting out the code that updates the quantity.
2. Redux State Update:
In your addItemsToCart action, it seems like you are passing the entire cartItems array to setLocalStorage, which might be causing issues.
These changes should help ensure that both the local storage and the Redux state are updated correctly.
From what I can see it looks like the issue is cause by
const newItem = item[0][0];
.In
setLocalStorage
item
is the array of cart items.item[0]
refers to the very first cart item object. Sinceitem[0]
is not an arrayitem[0][0]
is undefined.This causes an issue when searching the
cartItems
array retrieved from localStorage. Thex.product === newItem.product
check is never true. In fact, I believe this should be throwing an error becausenewItem
is undefined. If it isn’t then I may just be missing something from the code.In either case, the "persisting the cart to localStorage" should probably be moved into the reducer so (A) you don’t write duplicate code to add an item, (B) you can persist the updated state, and (C) initialize the state from localStorage.