Search code examples
javascriptreactjsredux

Add quantity in eshop in react-redux


I built an eshop and struggle find the syntax in order to multiply quantity of a product in the "Cart". I have managed to "add to cart" the products however does not update the quantity of the product added. It adds the product everytime I click "addToCart". I am using redux so I know that I should write additional code in the reducer file. My reducer file code is the following:

import { ADD_TO_CART } from './constants'
import { REMOVE_FROM_CART } from './constants'


const initialState = {
    cart: [],
  }
const ShoppinReducer = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TO_CART:
      const newCart = [...state.cart]
      
      newCart.push(action.payload)
      return {
        ...state,
        cart: newCart
      }

    case REMOVE_FROM_CART:
      const cart = [...state.cart]
      const updatedCart = cart.filter(item => item.id !== action.payload.id)
      return {
        ...state,
        cart: updatedCart
      }
    
    default:
    return state
  }
}
  export default ShoppinReducer

and my "Cart" component is the following:

import React, { Component } from "react"
import { Card, CardBody, CardHeader, CardTitle, Row, Col } from "reactstrap"
import PanelHeader from "components/PanelHeader/PanelHeader.js"
import { connect } from "react-redux";
import { removeCart} from "../redux/actions";


class Cart extends Component {
   removeFromCart = (product) => {
    const cartProducts = this.props.cart 
    const updatedCartProducts = cartProducts.filter(item => item.id !== product.id);
  
  }

  render () {
    const cartProducts = this.props.cart
    return (
      <>
        <PanelHeader size="sm" />
        <div className="content">
          <Row>
            <Col xs={12}>
              <Card>
                <CardHeader>
                  <CardTitle tag="h4">Products List</CardTitle>
                </CardHeader>
                <CardBody>
                <table class="table table-striped table-hover">
                  <thead>
                    <tr>
                      <th scope="col"><strong>#</strong></th>
                      <th scope="col"><strong>Name</strong></th>
                      <th scope="col"><strong>Code Item</strong></th>
                      <th scope="col"><strong>Quantity</strong></th>
                      <th scope="col"><strong>Price Total</strong></th>
                    </tr>
                  </thead>
                    <tbody>
                      {cartProducts.length > 0 && cartProducts.map((cartProduct, index) => (             
                      <tr key={cartProduct.id}>
                    <th scope="row">{index +1}</th>
                    <td>{cartProduct.title}</td>
                    <td>{cartProduct.code}</td>
                    <td>{cartProduct.quantity}</td>
                    <td>{cartProduct.price}</td>
                    <td><button onClick ={() => this.props.removeCart(cartProduct)} className="btn btn-danger cart-button px-4">Remove</button></td>
                      </tr>))}
                    </tbody>
                </table>
              </CardBody>
            </Card>
          </Col>
        </Row>
      </div>
    </>
    )
  }
}


const mapStateToProps = (state)=> {
  return {
      cart: state.cart
       }
  }

const mapDispatchToProps = (dispatch) => { 
      return {
        removeCart: (product) => {dispatch(removeCart(product))}
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Cart);

Bare in mind that "addToCart" button lives in other component however, I posted "Cart" component in order to display how the structure of the "Cart" is! Thank you in advance!


Solution

  • Before pushing any item to your cart, you need to check whether the items already exist in the cart or not, if it exists you should update the quantity instead. You can rewrite the ADD_TO_CART case in your reducer to something like this:

    const initialState = {
        cart: [],
      }
    const ShoppinReducer = (state = initialState, action) => {
      switch (action.type) {
        case ADD_TO_CART:
          let newCart = [...state.cart]
          let itemIndex = state.cart.findIndex(obj=>obj.id===action.payload.id)  
          let currItem = state.cart[itemIndex]
    
          if(currItem){
                currItem.quantity = parseInt(currItem.quantity) + 1
                state.cart[itemIndex] = currItem
                newCart = [...state.cart]
            }
            else{
                
                newCart = newCart.concat(action.payload)
            }
            
            return {
              cart: newCart
            }
    
        case REMOVE_FROM_CART:
          const cart = [...state.cart]
          const updatedCart = cart.filter(item => item.id !== action.payload.id)
          return {
            ...state,
            cart: updatedCart
          }
        
        default:
        return state
      }
    }