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.
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:
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: "w3wiki bag" , price: 109.95, description: "Your perfect pack for everyday use and walks in the forest." , category: "bag" , image: "https://practice.w3wiki.net/_next/image?url=https%3A%2F%2Fmedia.w3wiki.net%2Fimg-practice%2FMaskGroup31-1651641966.png&w=640&q=75" , rating: { rate: 3.9, count: 120, }, }, { id: 2, title: "w3wiki tshirt" , price: 22.3, description: "Slim-fitting style,black tshirt. From w3wiki" , category: "men's clothing" , image: "https://practice.w3wiki.net/_next/image?url=https%3A%2F%2Fmedia.w3wiki.net%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:
Contact Us