Horje
Implementing Add to Cart functionality using Redux toolkit in React

Add To Cart functionality is one of the important components of the E-commerce platform. In this article, we are going to learn how to implement Add to Cart functionality using React JS and Redux Toolkit.

Preview of final output: Let us have a look at how the final output will look like.

prv

Prerequisites

Approach to implement Add to Cart Functionality:

  • Create five folders named Cart, Components, Pages, Reducer and Slices in src directory and create index.jsx and RenderCartItems.jsx in Cart, Product_card.jsx in Components, Home.jsx in Pages, index.jsx in Reducer and CartSlice.jsx in Slices respectively.
  • Implement store inside index.js file as given in example.
  • Implement cartReducer inside index.js file in reducer folder.
  • Create CartSlice.jsx in Slices folder and implement functionality of add to cart and remove from cart in it.
  • Create Home.jsx page in Pages folder and fetch product details.
  • Inside Cart folder create index.js and RenderCartItems.jsx to create UI for cart.
  • In last step we will call Home page and cart in App.js file.

Steps to Create and Configure React App with redux toolkit

Step 1: Create a react app using command “npx create-react-app app-name”.

npx create-react-app app-name

Step 2: Install the required dependencies

npm install react-redux @reduxjs/toolkit
npm install react-hot-toast
npm i react-router-dom react-icons

Project Structure:

pj-str-

The updated dependencies in package.json file will look like:

"dependencies": {
"@reduxjs/toolkit": "^2.0.1",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.12.0",
"react-redux": "^9.0.4",
"react-router-dom": "^6.21.1",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
}

Example: Create the folder structure and insert the following files accordingly.

JavaScript
// Cart/index.jsx

import { useSelector } from "react-redux"
import RenderCartItems from "./RenderCartItems"

export default function Cart() {
    const {total, totalItems} = useSelector((state) => state.cart) 
    return (
        <div >
            <h1>Your Cart</h1>
            <p >{totalItems} Items in cart</p>
            {
                total>0 
                ? (
                    <div >
                        <RenderCartItems /> 
                    </div>
                )
                : (
                    <p>Your Cart is empty</p>
                )
            }
        </div>
    )
}
JavaScript
// Cart/RenderCartItems.jsx
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { RiDeleteBin6Line } from "react-icons/ri";
import { removeFromCart } from "../Slices/CartSlice";

export default function RenderCartItems() {
    const { cart } = useSelector((state) => state.cart);
    const dispatch = useDispatch();

    return (
        <div>
            {cart.map((dataObj, index) => (
                <div
                    key={index}
                    className={`flex w-full flex-wrap i
                                tems-start justify-between gap-6 
                        ${
                            index !== cart.length - 1 &&
                            "border-b border-b-richblack-400 pb-6"
                        } 
                        ${index !== 0 && "mt-6"} `}
                >
                    <div>
                        <div>{dataObj.title}</div>
                        <img
                            src={dataObj.image}
                            width={200}
                            height={150}
                            alt=""
                        />
                        <p>{dataObj.description}</p>
                    </div>

                    <div>
                        <button
                            onClick={() =>
                                dispatch(removeFromCart(dataObj._id))
                            }
                        >
                            <RiDeleteBin6Line size={20} />
                        </button>
                    </div>
                </div>
            ))}
        </div>
    );
}
JavaScript
// Components/Product_cart.jsx

import React from 'react'
import { addToCart } from '../Slices/CartSlice';
import { useDispatch } from 'react-redux'; 

const Product_card = ({ dataObj }) => {
    const dispatch = useDispatch();

    const handleAddToCart = () => {
        console.log("dispatching add to cart")
        dispatch(addToCart(dataObj)); 
        return;
    }

    return (
        <div
            style={{
                display: 'flex',
                flexWrap: 'wrap',
                gap: '70px',
                justifyContent: 'space-around',
                marginTop: '70px'
            }}
        >
            <div
                style={{
                    width: "15em",
                    backgroundColor: "#35D841",
                    padding: 2,
                    borderRadius: 10,
                    marginBlock: 10,
                }}
            >
                <p style={{ fontSize: 20, color: 'black' }}>{dataObj.title}</p>
                <img src={dataObj.image} alt="" height={200} width={200} />
                <p>{dataObj.description}</p>
                <button
                    onClick={handleAddToCart}
                >
                    Add to cart
                </button>
            </div>
        </div>
    )
}

export default Product_card
JavaScript
// Pages/Home.jsx

import React, { useState } from "react";
import { FaCartArrowDown } from "react-icons/fa";
import { Link } from "react-router-dom";
import Product_card from "../Components/Product_card";

const items = [
    {
        id: 1,
        title: "GeeksForGeeks bag",
        price: 109.95,
        description:
            "Your perfect pack for everyday use and walks in the forest.",
        category: "bag",
        image: "https://practice.horje.org/_next/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fimg-practice%2FMaskGroup31-1651641966.png&w=640&q=75",
        rating: {
            rate: 3.9,
            count: 120,
        },
    },
    {
        id: 2,
        title: "GeeksForGeeks tshirt",
        price: 22.3,
        description: "Slim-fitting style,black tshirt. From horje",
        category: "men's clothing",
        image: "https://practice.horje.org/_next/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fimg-practice%2FGroup7895-1651644285.png&w=640&q=75",
        rating: {
            rate: 4.1,
            count: 259,
        },
    },
];

const Home = () => {
    return (
        <div>
            <Link to={"/cart"}>
                <FaCartArrowDown size={40} color="#35D841" />
            </Link>
            <div
                style={{
                    display: "Flex",
                    justifyContent: "space-around",
                }}
            >
                {items.map((dataObj, index) => {
                    return <Product_card dataObj={dataObj} />;
                })}
            </div>
        </div>
    );
};

export default Home;
JavaScript
// Reducer/index.jsx

import { combineReducers } from "@reduxjs/toolkit";

import cartReducer from "../Slices/CartSlice"

const rootReducer = combineReducers({
    cart: cartReducer,
})

export default rootReducer
JavaScript
// Slices/CartSlice.jsx

import { createSlice } from "@reduxjs/toolkit";
import { toast } from "react-hot-toast";

const initialState = {
    cart: localStorage.getItem("cart")
        ? JSON.parse(localStorage.getItem("cart"))
        : [],
    total: localStorage.getItem("total")
        ? JSON.parse(localStorage.getItem("total"))
        : 0,
    totalItems: localStorage.getItem("totalItems")
        ? JSON.parse(localStorage.getItem("totalItems"))
        : 0,
}

const cartSlice = createSlice({
    name: "cart",
    initialState,
    reducers: { 
        addToCart: (state, action) => {
            const item = action.payload
            
            state.cart.push(item) 
            state.totalItems++
            state.total += item.price 
            localStorage.setItem("cart", JSON.stringify(state.cart))
            localStorage.setItem("total", JSON.stringify(state.total))
            localStorage.setItem("totalItems", JSON.stringify(state.totalItems)) 
            toast.success("Item added to cart")
        },
        
        removeFromCart: (state, action) => {
            const itemId = action.payload
            const index = state.cart.findIndex((item) => item._id === itemId)

            if (index >= 0) {
                
                state.totalItems--
                state.total -= state.cart[index].price
                state.cart.splice(index, 1) 
                localStorage.setItem("cart", JSON.stringify(state.cart))
                localStorage.setItem("total", JSON.stringify(state.total))
                localStorage.setItem("totalItems", JSON.stringify(state.totalItems)) 
                toast.success("Item removed from cart")
            }
        },

    }
})

export const { addToCart, resetCart, removeFromCart } = cartSlice.actions
export default cartSlice.reducer;
JavaScript
// App.js

import './App.css';
import { Route, Routes } from "react-router-dom";
import Cart from "./Cart/index"
import Home from "./Pages/Home";

function App() {
    return (
        <div className="App">
            <Routes>
                <Route path="/cart" element={<Cart />} />
                <Route path="/" element={<Home />} />
            </Routes>
        </div>
    );
}

export default App;
JavaScript
// index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import rootReducer from './Reducer';
import { Provider } from "react-redux";
import { configureStore } from "@reduxjs/toolkit"
import { BrowserRouter } from 'react-router-dom';
import { Toaster } from 'react-hot-toast';
const root = ReactDOM.createRoot(document.getElementById('root'));

const store = configureStore({
    reducer: rootReducer,
})

root.render(
    <React.StrictMode>
        <Provider store={store}>
            <BrowserRouter>
                <App />
                <Toaster />
            </BrowserRouter>
        </Provider>
    </React.StrictMode>
);
reportWebVitals();

Steps to Run the Application:

Step 1: Type following command in your terminal.

npm start

Step 2: Locate the given URL in your browser.

http://localhost:3000/

Output:





Reffered: https://www.geeksforgeeks.org


ReactJS

Related
Difference between useState and useReducer Difference between useState and useReducer
State Management in React – Hooks, Context API and Redux State Management in React – Hooks, Context API and Redux
React Tutorial React Tutorial
What is useDeferredValue hook and how to use it? What is useDeferredValue hook and how to use it?
Using Fonts in Next JS(Google Fonts, Tailwind CSS) Using Fonts in Next JS(Google Fonts, Tailwind CSS)

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
11