I'm trying to make an ecommerce for my personal project and I'm trying to use everything I've learned to do so. I currently have this code that allows you to store cartItems in a local Storage, but I believe it's incorrect what I did because in this scenario, for example, user 1 added his items to the cart or products to the cart, and then user 2 can access or have the same cart when I login with them. Which is the best practice or choice for the user to save cartItems? Or, rather, what should I do?
Currently the technology I use the M(ongoDB)E(xpress)R(eact)N(odejs)G(raphql) and Apollo for my state management.
Code
CartContext:
import { createContext, useState, useContext, useEffect } from "react";
import { AuthContext } from "../auth";
export const CartContext = createContext();
export const CartProvider = ({ children }) => {
const { user } = useContext(AuthContext);
const cartFromLocalStorage =
(typeof window !== "undefined" &&
JSON.parse(localStorage.getItem("cart"))) ||
[];
const [cartItems, setCartItem] = useState(cartFromLocalStorage);
useEffect(() => {
if (typeof window !== "undefined") {
if (user) { // This just shows if the user is loggedIn
localStorage.setItem("cart", JSON.stringify(cartItems));
}
}
}, [cartItems]);
return (
<CartContext.Provider value={[cartItems, setCartItem]}>
{children}
</CartContext.Provider>
);
};
This is my CartContext, where I can see what the user has added to their cart and call it whenever I want because it's a context that doesn't require to pass props to a component.
Shop:
import { useContext } from "react";
import { useQuery } from "@apollo/react-hooks";
import { FETCH_PRODUCTS_QUERY } from "../util/graphql/Queries";
import { Grid, Transition } from "semantic-ui-react";
import ProductCard from "../components/products/ProductCard";
import { CartContext } from "../context/cart/CartContext";
function Shop() {
const { loading, data: Products } = useQuery(FETCH_PRODUCTS_QUERY);
const { getProducts: products } = { ...Products };
const [cartItems, setCartItems] = useContext(CartContext);
const addToCart = (product) => {
const exist = cartItems.find((x) => x.id === product.id);
if (exist) {
setCartItems(
cartItems.map((x) =>
x.id == product.id ? { ...exist, quantity: exist.quantity + 1 } : x
)
);
} else {
setCartItems([...cartItems, { ...product, quantity: 1 }]);
}
};
const ProductList = products?.map((product) => (
<Grid.Column key={product.id} style={{ marginBottom: 20 }}>
<ProductCard
product={product}
addToCart={(product) => addToCart(product)}
/>
</Grid.Column>
));
return (
<>
<Grid columns={3}>
<Grid.Row className="page-title">
<h1>Recent Products</h1>
</Grid.Row>
<Grid.Row>
{loading ? (
<h1>Loading products..</h1>
) : (
<Transition.Group>{ProductList}</Transition.Group>
)}
</Grid.Row>
</Grid>
</>
);
}
export default Shop;
This is my Shop or where the Product is located as shown I passed the addToCart function to the ProductCard Component.
ProductCard:
import { Image, Card } from "semantic-ui-react";
import Link from "next/link";
import Rating from "../reviews/Rating";
function ProductCard({ product, addToCart }) {
const {
id,
name,
featureImage,
productCurrentPrice,
productPreviousPrice,
rating,
numReviews,
} = product;
return (
<>
<Card>
<Image
src={featureImage}
width={200}
height={200}
alt="Product Image"
className="product-image"
/>
<Card.Content>
<Card.Header>
<Link href={`/products/${id}`}>{name}</Link>
</Card.Header>
<Card.Meta>
<span className="date">
₱{productCurrentPrice.toLocaleString()}
</span>
<span className="date">
<strike>₱{productPreviousPrice.toLocaleString()}</strike>
</span>
<span className="header">{percentOff} % OFF</span>
</Card.Meta>
</Card.Content>
<Card.Content extra>
<div className="ui two buttons">
<button
className="ui basic green button"
onClick={() => addToCart(product)}
>
Add To Cart
</button>
</div>
</Card.Content>
</Card>
</>
);
}
export default ProductCard;
This is my ProductCard Component which when addToCart it will go to the localStorage just like this:
As shown above, the image the cart key is where all the products I added is inputted there. even when I logout the cartItem is still shown there, which it should not.
If you need anymore clarification or explanation, I can provide it, if code I will also provide I will be transparent as I can.
