How I created a CART functionality for my React e-commerce project.

·

3 min read

In an e-commerce application,Cart is one of the core functionality that allows the user to add,remove,increase,decrease,clear products that they want to buy.

In the Cart functionality that I created, Items that the users added into their cart was stored into the local Storage in an Array as Cart Items.

const Storage=(cartItems)=>{
    localStorage.setItem('cart',JSON.stringify(cartItems.length>0 ? cartItems:[]))
}

A function was then created to calculate the total items present in the cart and the total price of all the items in the cart.

const sumItems=(cartItems)=>{
    Storage(cartItems)
    let totalCount=cartItems.reduce((total,item)=>total+item.quantity,0)
    let totalAmount=cartItems.reduce((total,item)=>total+item.quantity*item.price,0)
        return {totalAmount,totalCount}
}

The Cart Operations were made using the useReducer hook. useReducer hook allows us to update parts of Component's State when certain actions are dispatched. It carries initial state and reducer function as an argument and provides us state variable and dispatch function to update the state.

const [state, dispatch] = useReducer(reducer, initialState);

At first, Initial State of the cart was defined. The items present in the cart were retrieved from the local storage and an initial state was defined with cart Items , Sum Items function created earlier and a checkout variable that was initially set to false . A spread operator was used with Sum items function so that incoming array values generated from different dispatch actions no matter how many can be inserted into the array and total count and total amount can be calculated .

const Storage = localStorage.getItem("cart")
  ? JSON.parse(localStorage.getItem("cart"))
  : [];

const initialState = {
  cartItems: Storage,
  ...sumItems(Storage),
  checkout: false,
};

Several dispatch function were then created for performing different cart actions.

const [state,dispatch]=useReducer(CartReducer,initialState)

    const increase=(payload)=>{
        dispatch({type:INCREASE,payload})
    }

    const decrease=(payload)=>{
        dispatch({type:DECREASE,payload})
    }

    const addProduct=(payload)=>{
        dispatch({type:ADD_TO_CART,payload})
    }

    const removeProduct=(payload)=>{
        dispatch({type:REMOVE_ITEM,payload})
    }

    const clearCart=()=>{
        dispatch({type:CLEAR_CART})
    }

    const checkout=()=>{
        dispatch({type:CHECKOUT})
    }

Then Reducer function was defined that updated the state depending upon the actions dispatched.

  • ADD_TO_CART:We first checked if the item user clicked on was already present in the cart or not and if was not then the item was pushed into the cart Items array along with a quantity variable with value one.
  • REMOVE_ITEM:We filtered the cart Items array with the item id of the product that the user chose to remove.
  • INCREASE:We searched for the index of the item which the user chose to increase and increased the quantity of the product by one each time.
  • DECREASE:Similar to increase,we searched for the index of the item which the user chose to decrease and decreased the quantity of the product by one each time.
  • CLEAR_CART:We replaced the value of sum items and cart items array to empty array.
  • CHECKOUT:We replaced the value of sum items and cart items array to empty array and changed the value of checkout variable from false to true.
const CartReducer=(state,action)=>{
    switch(action.type){
        case 'ADD_TO_CART':{
            if(!state.cartItems.find(item=>item.id===action.payload.id)){
                state.cartItems.push({...action.payload,quantity:1})
            }
            return{
                ...state,
                ...sumItems(state.cartItems),
                cartItems:[...state.cartItems]
            }
        }
        case 'REMOVE_ITEM':{
            return{
                ...state,
                ...sumItems(state.cartItems.filter(item=>item.id!==action.payload.id)),
                cartItems:[...state.cartItems.filter(item=>item.id!==action.payload.id)]
            }
        }
        case 'INCREASE':{
            state.cartItems[state.cartItems.findIndex(item=>item.id===action.payload.id)].quantity++
            return{
                ...state,
                ...sumItems(state.cartItems),
                cartItems:[...state.cartItems]
            }
        }
        case 'DECREASE':{

            state.cartItems[state.cartItems.findIndex(item=>item.id===action.payload.id)].quantity--
            return{
                ...state,
                ...sumItems(state.cartItems),
                cartItems:[...state.cartItems]
            }
        }
        case 'CLEAR_CART':{
            return{
                ...sumItems([]),
                cartItems:[]
            }
        }
        case 'CHECKOUT':{
            return{
                ...sumItems([]),
                cartItems:[],
                checkout:true
            }
        }
         default:{
             return state
         }
    }

All the dispatch functions were then passed to all the required components using useContext hook and the respective actions were then linked to the respective buttons upon clicking which different cart operations were performed.