I am new to react. I am not able to figure out the solution. On adding a product to the cart I am not able to see it in the cart scree. Please suggest any changes. The error I am getting is : state.cartItems is not iterable (cartReducers.js:26).
CART ACTION:
const { data } = await axios.get(`/api/products/${id}`)
console.log(data);
dispatch({
type: CART_ADD_ITEM,
payload: {
product: data._id,
name: data.name,
image: data.image,
price: data.price,
countInStock: data.countInStock,
qty,
},
})
console.log(data);
console.log(getState().cart.cartItems)
localStorage.setItem('cartItems', JSON.stringify(getState().cart.cartItems))
}
REDUCER:
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,
cartItems: state.cartItems?.map((x) =>
x.product === existItem.product ? item : x
),
}
} else {
return {
...state.cartItems,
cartItems: [...state.cartItems, item],
}
}
case CART_REMOVE_ITEM:
return {
...state.cartItems,
cartItems: state.cartItems.filter((x) => x.product !== action.payload),
}
default:
return state
}
}
Below is the cart component. I want to access all the cart items and calculate total quantity and price. CART COMPONENT:
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, removeFromCart } from '../actions/cartActions'
const CartScreen = ({ match, location, history }) => {
const productId = match.params.id
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])
const removeFromCartHandler = (id) => {
dispatch(removeFromCart(id))
}
return (
<Row>
<Col md={8}>
<h1>Shopping Cart</h1>
{cartItems?.length === 0 ? (
<Message>
Your cart is empty <Link to='/'>Go Back</Link>
</Message>
) : (
<ListGroup variant='flush'>
{cartItems?.map((item) => (
<ListGroup.Item key={item.product}>
<Row>
<Col md={2}>
<Image src={item.image} alt={item.name} fluid rounded />
</Col>
<Col md={3}>
<Link to={`/product/${item.product}`}>{item.name}</Link>
</Col>
<Col md={2}>${item.price}</Col>
<Col md={2}>
<Form.Control
as='select'
value={item.qty}
onChange={(e) =>
dispatch(
addToCart(item.product, Number(e.target.value))
)
}
>
{[...Array(item.countInStock).keys()]?.map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))}
</Form.Control>
</Col>
<Col md={2}>
<Button
type='button'
variant='light'
onClick={() => removeFromCartHandler(item.product)}
>
<i className='fas fa-trash'></i>
</Button>
</Col>
</Row>
</ListGroup.Item>
))}
</ListGroup>
)}
</Col>
<Col md={4}>
<Card>
<ListGroup variant='flush'>
<ListGroup.Item>
<h2>
Subtotal ({cartItems?.reduce((acc, item) => acc + item.qty, 0)})
items
</h2>
Rs.
{cartItems?.reduce((acc, item) => acc + item.qty * item.price, 0)
.toFixed(2)}
</ListGroup.Item>
</ListGroup>
</Card>
</Col>
</Row>
)
}
export default CartScreen