How to make data inside of cart become Persistent - NextJS
Updated at: 1 April 2023Deepak PainkraIn this article, I will be teaching you how to create a card state for products using NextJS,
When we click the button, it will get added to the cart. And when we press to remove button, it gets removed from the cart, and it has an increment & decrement function.
Note:- I'm expecting that you have already created your NavBar to follow this tutoring, and I have shared all these codes in one place for clarification.
Creating NextJS App
First, let's create a NextJS app by running this commandWe are implementing this feature on every page. So that those users will be able to see their items on every page, So let's open up the app.js file
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import "@/styles/globals.css";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export default function App({ Component, pageProps }) {
const [cart, setCart] = useState({});
const [subTotal, setSubTotal] = useState(0);
const router = useRouter();
}
And will create two constants first cart and the second subTotal. The cart value is an empty object because we are setting its value, and the subTotal will be zero initially, which means the number of an item.
Let's create a first method addToCart with the arrow function, then after, we will add all these items such as price, qty, name, size, variant
const addToCart = (itemCode, qty, price, name, size, variant) => {
let newCart = cart;
toast.success("Item added successfully!", {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty + qty;
} else {
newCart[itemCode] = { qty: 1, price, name, size, variant };
}
setCart(newCart);
saveCart(newCart);
};
After that, we will create a variable name newCart, and the newCart is equal to cart, and add an if and else statement. It says that if an item is in the cart, addToCart will increment the quantity, and if not, then it will add the object name such as name, qty, price, size, and variant, then after setCart is newCart, and then we will save it by saveCart
We are using react-tostify for notification, and if you have not installed yet, then install it by using this command,
Afterwards, we create another method clearCart then will implement the arrow function
const clearCart = () => {
setCart({});
saveCart({});
toast.error('Cart Clear!', {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
};
setCart will be an empty object {} because it will take time to set. And also saveCart will be an empty object{}
After that, we will create another object RemoveFromCart with the arrow function. We will create an object newCart and parse JSON.parse(JSON.strigyfy(cart));, which will select all the entities. And this feature is kind similar to the addToCart function, and it says that if an item is in the cart, then it will decrement the quantity,
const RemoveFromCart = (itemCode, qty, price, name, size, variant) => {
let newCart = JSON.parse(JSON.stringify(cart));
toast.warn('Item removed!', {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty - qty;
if (newCart[itemCode].qty <= 0) {
delete newCart[itemCode];
}
}
setCart(newCart);
saveCart(newCart);
};
If not less than zero, then it will delete the itemCode, and it will set the setCart is newCart and also saveCart is newCart
Note:- an itemCode is an object,
Okay, let's create another method saveCart,
const saveCart = (myCart) => {
localStorage.setItem("cart", JSON.stringify(myCart));
let subt = 0;
let keys = Object.keys(myCart);
for (let i = 0; i < keys.length; i++) {
subt += myCart[keys[i]].price * myCart[keys[i]].qty;
}
setSubTotal(subt);
};
and the same will implement an arrow function
Afterwards, let's create another method name buyNow with an arrow function, and select all the objects, also create a variable name newCart,
const buyNow = (itemCode, qty, price, name, size, variant) => {
let newCart = { itemCode: { qty: 1, price, name, size, variant } };
setCart(newCart);
saveCart(newCart);
router.push("/checkout");
};
After adding the objects, it will push to the checkout page with the help of react-router
Showing product using Effect
It says that if the item is already in the cart, show it to the user, and if not. Then you clear the localStorage, In the end, we are returning to the Navbar
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import "@/styles/globals.css";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export default function App({ Component, pageProps }) {
const [cart, setCart] = useState({});
const [subTotal, setSubTotal] = useState(0);
const router = useRouter();
useEffect(() => {
console.log("load from app.js");
try {
if (localStorage.getItem("cart")) {
setCart(JSON.parse(localStorage.getItem("cart")));
saveCart(JSON.parse(localStorage.getItem("cart")));
}
} catch (error) {
console.error(error);
localStorage.clear();
}
}, []);
const saveCart = (myCart) => {
localStorage.setItem("cart", JSON.stringify(myCart));
let subt = 0;
let keys = Object.keys(myCart);
for (let i = 0; i < keys.length; i++) {
subt += myCart[keys[i]].price * myCart[keys[i]].qty;
}
setSubTotal(subt);
};
const addToCart = (itemCode, qty, price, name, size, variant) => {
let newCart = cart;
toast.success("Item added successfully!", {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty + qty;
} else {
newCart[itemCode] = { qty: 1, price, name, size, variant };
}
setCart(newCart);
saveCart(newCart);
};
const buyNow = (itemCode, qty, price, name, size, variant) => {
let newCart = { itemCode: { qty: 1, price, name, size, variant } };
setCart(newCart);
saveCart(newCart);
router.push("/checkout");
};
const clearCart = () => {
setCart({});
saveCart({});
toast.error('Cart Clear!', {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
};
const RemoveFromCart = (itemCode, qty, price, name, size, variant) => {
let newCart = JSON.parse(JSON.stringify(cart));
toast.warn('Item removed!', {
position: "top-center",
autoClose: 1500,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
theme: "light",
});
if (itemCode in cart) {
newCart[itemCode].qty = cart[itemCode].qty - qty;
if (newCart[itemCode].qty <= 0) {
delete newCart[itemCode];
}
}
setCart(newCart);
saveCart(newCart);
};
return (
<>
<Navbar
key={subTotal}
cart={cart}
addToCart={addToCart}
RemoveFromCart={RemoveFromCart}
clearCart={clearCart}
subTotal={subTotal}
/>
<ToastContainer
position="top-center"
autoClose={1500}
limit={5}
hideProgressBar
newestOnTop
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
theme="light"
/>
<Component
cart={cart}
addToCart={addToCart}
buyNow={buyNow}
RemoveFromCart={RemoveFromCart}
clearCart={clearCart}
subTotal={subTotal}
{...pageProps}
/>
<Footer />
</>
);
}
T-shirt Pages
creating a t-shirt.js file inside pages/ directory, and for further implementation, I'm giving you the GitHub Links. In the future, maybe I will complete this article
Support Us
Your support helps us continue our work. Please consider making a donation.
Donate with PayPal