Skip to content
Advertisement

(React and Redux) Problem with adding items to the shopping cart

I am following a tutorial, where we are building a shopping cart, which is still unfinished, but I would like to solve this problem before continuing in the tutorial.

The thing is, that when I try to add any item to the cart, the cart is still saying me, that my shopping cart is empty. You can notice in the url of this picture below, that I have added the item with id number 1 to the shopping cart and quantity (qty) is also 1. enter image description here

But the shopping cart should not respond this kind of message after adding an item into it. At this stage, in which the code is, the response should be just a blank page.

This didnĀ“t work yet when I was trying to console.log the cartItems – it was an empty array for me, but the instructor was receiving the data about the products, which were added to cart. So that might be a clue.

Please take a look at the following files and let me know, if You will be able to see any hint or a solution.

CartScreen.js –

import React, {useEffect} from 'react'
import { Link } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { Row, Col, ListGroup, Image, Form, Button, Card } from 'react-bootstrap'
import Message from '../components/Message'
import { addToCart } from '../actions/cartActions'


function CartScreen({ match, location, history }) {
    const productId = match.params.div
    const qty = location.search ? Number(location.search.split('=')[1]) : 1
    
    const dispatch = useDispatch()

    const cart = useSelector(state => state.cart)
    const { cartItems } = cart
    
    useEffect(() =>{
        if(productId){
            dispatch(addToCart(productId, qty))
        }    
    }, [dispatch, productId, qty])
    return (
        <Row>
            <Col md={8}>
             <h1>Shopping Cart</h1>
             {cartItems.length === 0 ? (
                 <Message variant='info'>
                     Your cart is empty <Link to='/'>Go Back</Link>
                 </Message>
             ) : (
                 <listGroup variant='flush'>

                 </listGroup>
             )}
            </Col>

            <Col md={4}>
                
            </Col>
        </Row>
    )
}

export default CartScreen

cartActions.js –

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))
}

cartReducers.js –

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
    }
}

cartConstants.js –

export const CART_ADD_ITEM = 'CART_ADD_ITEM'
export const CART_REMOVE_ITEM = 'CART_REMOVE_ITEM'

store.js –

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 cartItemsFromStorage = localStorage.getItem('cartItems') ?
        JSON.parse(localStorage.getItem('cartItems')) : []

const initialState = {
    cart: { cartItems: cartItemsFromStorage }
}

const middleware = [thunk]

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

export default store

ProductScreen.js –

import React, { useState, useEffect } from "react";
import { useDispatch, useSelector } from 'react-redux'
import { Link } from "react-router-dom";
import { Row, Col, Image, ListGroup, Button, Card, Form } from "react-bootstrap";
import Rating from "../components/Rating";
import Loader from "../components/Loader";
import Message from "../components/Message";
import { listProductDetails } from '../actions/productActions'

function ProductScreen({ match, history }) {
  const[qty, setQty] = useState(1)

  const dispatch = useDispatch()
  const productDetails = useSelector(state => state.productDetails)
  const { loading, error, product } = productDetails
 
  useEffect(() => {
     dispatch(listProductDetails(match.params.id))
  },[dispatch, match])

  const addToCartHandler = () => {
    history.push(`/cart/${match.params.id}?qty=${qty}`)
  }

  return (
    <div>
      <Link to="/" className="btn btn-light my-3">
        Go Back
      </Link>
      {loading ?
         <Loader/>
         : error
             ? <Message variant='danger'>{error}</Message>
         :(
          <Row>
          <Col md={6}>
            <Image src={product.image} alt={product.name} fluid />
          </Col>
  
          <Col md={3}>
            <ListGroup variant="flush">
              <ListGroup.Item>
                <h3>{product.name}</h3>
              </ListGroup.Item>
  
              <ListGroup.Item>
                <Rating
                  value={product.rating}
                  text={`${product.numReviews} reviews`}
                  color={"#f8e825"}
                />
              </ListGroup.Item>
  
              <ListGroup.Item>Price: ${product.price}</ListGroup.Item>
  
              <ListGroup.Item>Description: {product.description}</ListGroup.Item>
            </ListGroup>
          </Col>
  
          <Col md={3}>
            <Card>
              <ListGroup variant="flush">
                <ListGroup.Item>
                  <Row>
                    <Col>Price:</Col>
                    <Col>
                      <strong>${product.price}</strong>
                    </Col>
                  </Row>
                </ListGroup.Item>
  
                <ListGroup.Item>
                  <Row>
                    <Col>Status:</Col>
                    <Col>
                      {product.countInStock > 0 ? "In Stock" : "Out of Stock"}
                    </Col>
                  </Row>
                </ListGroup.Item>

                {product.countInStock > 0 && (
                  <ListGroup.Item>
                    <Row>
                      <Col>Qty</Col>
                      <Col xs='auto' className='my-1'>
                        <Form.Control
                          as="select"
                          value={qty}
                          onChange={(e) => setQty(e.target.value)}
                        >
                          {
                          
                            [...Array(product.countInStock).keys()].map((x) => (
                              <option key={x + 1} value={x + 1}>
                                {x + 1}
                              </option>
                            ))
                          }

                        </Form.Control>
                      </Col>
                    </Row>
                  </ListGroup.Item>
                )}


  
                <ListGroup.Item>
                  <Button
                    onClick={addToCartHandler}
                    className="btn-block"
                    disabled={product.countInStock == 0}
                    type="button"
                  >
                    Add to Cart
                  </Button>
                </ListGroup.Item>
              </ListGroup>
            </Card>
          </Col>
        </Row>
         )

      }

      
    </div>
  );
}

export default ProductScreen;

Advertisement

Answer

here is the error :

const productId = match.params.div

it should be “id” not div

const productId = match.params.id
Advertisement