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