Search code examples
javascriptreactjsreduxreact-redux

Implementing add to cart in React + Redux results in error, cannot fetch added products


So, I'm trying to add a product to cart, which is the object, specified by quantity which is passed in url parameters. It will look like this:

http://localhost:3000/cart/622d6150a1d5f82535d4b66c?qty=3

I managed to split the quantity (qty) parameter by using useLocation, but I somehow cannot console log the cartItems which contain the products that have been added to the cart.

import React, {useEffect} from 'react'
import {useDispatch, useSelector} from 'react-redux'
import {Link, useLocation, useNavigate, useParams, useSearchParams} from 'react-router-dom'
import {addToCart} from '../actions/cartActions'

export const CartScreen = () => {
  const productId = useParams()
  const history = useNavigate()
  const useQty = useLocation()

  const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1

  console.log(qty)
  const dispatch = useDispatch()

  const cart = useSelector((state) => state.cart)
  const {cartItems} = cart

  console.log(cartItems)

  useEffect(() =>{
    if(productId){
      dispatch(addToCart(productId, qty))
    }
  },[dispatch, productId, qty])



  return (
    <div>CartScreen</div>
  )
}

export default CartScreen

the console shows something like this, it shows 3 from the url parameter but shows an empty array where it should've been show the array of the products that I've been added to the cart. Also, What is the GET http://localhost:3000/api/products/[object%20Object] 404 (Not Found) mean? FYI, the products was fetched from mongodb which is in localhost:5000/api/products but get proxy through localhost:3000

console

If this is any help, as I'm also using Redux, here is my addToCart actions, the redux store file, cart reducers as well.

import axios from "axios";
import { CART_ADD_ITEM } from "../constants/cartConstants";


export const addToCart = (id, qty) => async (dispatch, getState) => {
    const {data} = await axios.get(`/api/products/${id}`)

    dispatch({
        type: CART_ADD_ITEM,
        payload: {
            product: data._id,
            name: data.name,
            image: data.image,
            price: data.price,
            countInStock: data.countInStock,
            qty
        }
    })

    localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems))
}
import {createStore, combineReducers, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import { productListReducer, productDetailsReducer } from './reducers/productReducers'
import { cartReducer } from './reducers/cartReducers'

const reducer = combineReducers({
    productList: productListReducer,
    productDetails: productDetailsReducer,
    cart: cartReducer,
})

const cartItemsFromLocalStorage = localStorage.getItem('cartItems') ? JSON.parse(localStorage.getItem('cartItems')) : []

const initialState = {
    cart: {cartItems: cartItemsFromLocalStorage},
}

const middleware = [thunk]

const store = createStore(reducer, 
    initialState, 
    composeWithDevTools(applyMiddleware(...middleware)))

export default store
import {CART_ADD_ITEM} from "../constants/cartConstants"

export const cartReducer = (state = {cartItems: []}, action) => {
    switch(action.type){
        case CART_ADD_ITEM:
            const item = action.payload

            const existItem = state.cartItems.find(x => x.product === item.product)

            if(existItem){
                return{
                    ...state,
                    cartItems: state.cartItems.map(x => x.product === existItem.product ? item : x),
                }
            } else {
                return{
                    ...state,
                    cartItems: [...state.cartItems, item]
                }

            }
        default:
        return state

    }
    
}

Solution

  • This is solved by using restructuring the variables in CartScreen.js like this:

    const {productId} = useParams()
    const useQty = useLocation()
    
    const qty = useQty.search ? Number(useQty.search.split('=')[1]) : 1
    

    To this:

    const { id } = useParams();
    const { search } = useLocation();
      
    const productId = id;
    const qty = search ? Number(search.split("=")[1]) : 1;
      
    

    Now it shows the product details in the array, I honestly don't know what is happening here. console