Search code examples
reduxreact-reduxredux-toolkit

Can't access object properties from state slice


I am trying to make a shopping cart slice for my web application using Redux-Toolkit. In my cartSlice.js file, I would like to have the functionality to be able to add/remove items to the cart, and increment/decrement the quantity of the items if there are already items in the cart. The main issue I am running into is not being able to access the quantity property from the cartSlice.js file.

Below is the code for the cart & cartSlice files, as well as the item component and storeItems file which is an array of objects the store has.

cart.js:

import { React } from 'react';
import { useSelector } from "react-redux";
import { selectCart } from './cartSlice';


export const Cart = () => {
    const cart = useSelector(selectCart);

    return (
        <div className="cart">
            {cart.cart?.map( (item) => (
                <p quantity={item.quantity} >{item.name} x{item.quantity}</p>
            ))}
        </div>
    )
}

cartSlice.js:

import { createSlice } from '@reduxjs/toolkit';


const cartSlice = createSlice({
    name: 'cart',
    initialState: {
        cart: [],
        total: 0,
    },
    reducers: {
        addToCart: (state, action) => {
            const itemInCart = state.cart.find((item) => item.id === action.payload.id);
            const item = state.cart.find((item) => item.id === action.payload);

            if (itemInCart > 1) {
                state.total += action.payload.price;
                item.quantity += 1;
            } else {
                state.cart.push({ ...action.payload, quantity:  1});
                state.total += action.payload.price;
                item.quantity += 1;
            }
        },
        removeItem: (state, action) => {
            const itemInCart = state.cart.find((item) => item.id === action.payload.id);
            const item = state.cart.find((item) => item.id === action.payload);

            if (itemInCart.quantity === 1) {
                const removeItem = state.cart.filter((item) => item.id !== action.payload.id);
                state.cart = removeItem;
                state.total -= action.payload.price;
                item.quantity -= 1;
            } else {
                item.quantity -= 1;
            }  
        },
    },
})

export const { addToCart, incrementQuantity, decrementQuantity, removeItem } = cartSlice.actions;
export const selectCart = (state) => state.cart;
export const cartReducer = cartSlice.reducer;

Item.js:

import { React } from 'react';
import styles from '../../styles/shopping.module.css';
import { addToCart, removeItem } from '../../features/Shopping/cart/cartSlice';
import { useDispatch } from "react-redux";


export default function Item({item}) {
    const dispatch = useDispatch();

    const onAddToCartHandler = (item) => {
        dispatch(addToCart(item));
    }
    const onRemoveFromCartHandler = (item) => {
        dispatch(removeItem(item));
    }

    return (
        <div key={item.id} className={styles.item}>
            {/* <img src={require('../../styles/image-not-found.jpg')} /> */}
            <img src={item.image} />
            <h3>{item.name}</h3>
            <p>Price: ${item.price}</p>
            <div className="buttons">
                    <button onClick={() => onAddToCartHandler(item)}>+</button>
                    <button onClick={() => onRemoveFromCartHandler(item)}>-</button>
            </div>
        </div>
    )
}

storeItems.js:

export const produce = [
    {
        id: 1,
        name: "Carrots",
        price: 2.89,
        image: "https://www.jessicagavin.com/wp-content/uploads/2019/02/carrots-7-1200.jpg",
        quantity: 0,
    },
    {
        id: 2,
        name: "Cucumbers",
        price: 0.99,
        image: "https://snaped.fns.usda.gov/sites/default/files/styles/crop_ratio_7_5/public/seasonal-produce/2018-05/cucumbers2.jpg?itok=YISLeW4e",
        quantity: 0,
    },
    {
        id: 3,
        name: "Bell peppers",
        price: 0.76,
        image: "https://hosstools.com/wp-content/uploads/2020/10/mini-belle-pepper-mix.jpg",
        quantity: 0,
    },
    {
        id: 4,
        name: "Avocados",
        price: 1.26,
        image: "https://blog.lexmed.com/images/librariesprovider80/blog-post-featured-images/avocadosea5afd66b7296e538033ff0000e6f23e.jpg?sfvrsn=a273930b_0",
        quantity: 0,
    },
    {
        id: 5,
        name: "Spinach",
        price: 2.99,
        image: "https://cdn.britannica.com/30/82530-050-79911DD4/Spinach-leaves-vitamins-source-person.jpg",
        quantity: 0,
    },
    {
        id: 6,
        name: "Kale",
        price: 2.30,
        image: "https://i0.wp.com/images-prod.healthline.com/hlcmsresource/images/AN_images/benefits-of-kale-1296x728-feature.jpg?w=1155&h=1528",
        quantity: 0,
    },
    {
        id: 7,
        name: "Tomatoes",
        price: 1.05,
        image: "https://www.almanac.com/sites/default/files/styles/or/public/image_nodes/tomatoes_helios4eos_gettyimages-edit.jpeg?itok=2owPswip",
        quantity: 0,
    }
]

Solution

  • As you have mentioned only some files code.You mentioned your backend working fine but in state you can't access quantity attribute. Its because of you have made small mistake in you cartSlice.js file.

    In item.js in dispatch method you have passed whole Item object to the reducers function, but in find method method in item variable you are matching item.id with whole item object. So its never gonna find any item. You have done this...

    dispatch(addToCart(item)); You have passed whole object.

    Instead of that use like this, may be it will give you access to the quantity. You have done this.. const item = state.cart.find((item) => item.id === action.payload);

    Do like this... const item = state.cart.find((item) => item.id === action.payload.id);

    also if you find any problems, try to log action in reducer to see what you are getting... Thank you...