How to increase the quantity on an item that already exists in my shopping cart?

Yo! I'm trying to figure out how I go about increasing the quantity of an item that already exists in cart/page.jsx, instead of it adding that same item again as a new element each time, but I can't figure it out. the repo is here: https://github.com/callum-laing/shopping-site
17 Replies
Tenkes
Tenkes3mo ago
I would put cart item in separate component, and then have state inside to handle quantity. Something like this:
const CartComponent = () => {
// ...

return (
<div className={Styles.cartContainer}>
{items.map(item => (
<CartItem item={item} />
))}
</div>
)
}

function CartItem({ item }) {
const [quantity, setQuantity] = useState<number>(item.quantity ?? 0)

const handleQuantity = action => {
switch (action) {
case '+':
setQuantity(prev => prev + 1)
break
case '-':
setQuantity(prev => prev - 1)
break
default:
throw new Error('Invalid action:', action)
}

const currentItems = JSON.parse(localStorage.getItem('items'))
const updatedItems = currentItems.map(i =>
i.id === item.id ? { ...i, quantity } : i
)

localStorage.setItem('items', JSON.stringify(updatedItems))
}

return (
<div className={Styles.cartItem}>
<img
className={Styles.cartImage}
src={item.image}
alt={item.name}
/>
<div className={Styles.itemDetails}>
<h3 className={Styles.CartTitle}>{item.name}</h3>
<p className={Styles.cartName}{item.price}</p>
<p>Quantity: {item.quantity}</p>
<button onClick={() => handleQuantity('+')}>+</button>
<button onClick={() => handleQuantity('-')}>-</button>
</div>
</div>
)
}
const CartComponent = () => {
// ...

return (
<div className={Styles.cartContainer}>
{items.map(item => (
<CartItem item={item} />
))}
</div>
)
}

function CartItem({ item }) {
const [quantity, setQuantity] = useState<number>(item.quantity ?? 0)

const handleQuantity = action => {
switch (action) {
case '+':
setQuantity(prev => prev + 1)
break
case '-':
setQuantity(prev => prev - 1)
break
default:
throw new Error('Invalid action:', action)
}

const currentItems = JSON.parse(localStorage.getItem('items'))
const updatedItems = currentItems.map(i =>
i.id === item.id ? { ...i, quantity } : i
)

localStorage.setItem('items', JSON.stringify(updatedItems))
}

return (
<div className={Styles.cartItem}>
<img
className={Styles.cartImage}
src={item.image}
alt={item.name}
/>
<div className={Styles.itemDetails}>
<h3 className={Styles.CartTitle}>{item.name}</h3>
<p className={Styles.cartName}{item.price}</p>
<p>Quantity: {item.quantity}</p>
<button onClick={() => handleQuantity('+')}>+</button>
<button onClick={() => handleQuantity('-')}>-</button>
</div>
</div>
)
}
btw I haven't tested this so there might be some bugs Also I noticed you're using Next.js, so you should know components/ directory should go outside of app/ directory. Right now you're creating "/components" route, which I guess you don't want
CDL
CDL3mo ago
I think i've set it up all wrong tbh lol
CDL
CDL3mo ago
No description
CDL
CDL3mo ago
first time using nextjs you mean like this?
CDL
CDL3mo ago
No description
CDL
CDL3mo ago
I'm kinda too deep into this to try and figure out what I pull from cart.jsx, to put into the cart component, it's all getting very uhh... confusing.. 😅
Tenkes
Tenkes3mo ago
| data.js
|
+---app
| | globals.css
| | layout.jsx
| | page.jsx
| | page.module.css
| |
| +---cart
| | cart.module.css
| | page.jsx
| |
| \---shop
| page.jsx
| shop.module.css
|
+---components
| \---Navbar
| index.jsx
| Navbar.module.css
|
\---public
\---images
shopping-cart.png
| data.js
|
+---app
| | globals.css
| | layout.jsx
| | page.jsx
| | page.module.css
| |
| +---cart
| | cart.module.css
| | page.jsx
| |
| \---shop
| page.jsx
| shop.module.css
|
+---components
| \---Navbar
| index.jsx
| Navbar.module.css
|
\---public
\---images
shopping-cart.png
This is example how it should look like. I'm not sure what Card.jsx is from Navbar/. If it's component that is used in multiple places that you should put it in components/, but if you're going to use it only in Navbar/ then you can create it there as well.
CDL
CDL3mo ago
you know what, I Navbar folder shouldn't even be there, I'm not entirely sure why it's there, how it got there, and how to get rid of the bloody thing lol
Tenkes
Tenkes3mo ago
What do you mean? Why not?
CDL
CDL3mo ago
it seems to be joint into the components folder? I can't see why lol
Tenkes
Tenkes3mo ago
I don't see a problem lol. If you mean why is it folder and not just file you can do both. By making it as folder you can put all stuff related to Navbar inside of there. And have index.jsx where you would put component itself. Then when you import it you would do
import Navbar from '@components/Navbar'
import Navbar from '@components/Navbar'
Just like if it was file Navbar.jsx
CDL
CDL3mo ago
I thin that is what I was trying to do but for some reason it now looks as "components / Navbar" Let me tidy up the filing here, it's quite the mess 😄
Tenkes
Tenkes3mo ago
Go for it
CDL
CDL3mo ago
That looks better
No description
No description
CDL
CDL3mo ago
Ok sorry, back to the original point, so is it quite messy to arrange the quantity to change if I keep everything inside app/cart/page.jsx? i tried your way of creating component/cartItem.jsx and moving it, which makes sense, but I got a little lost on what I remove from cart/page.jsx to make this possible
Tenkes
Tenkes3mo ago
Just inscreaseQuantity and decreaseQuantity. I believe the rest can stay in cart/page.jsx. You can either move them to CartItem and make them work with your new component or you can use my handleQuantity function.
CDL
CDL3mo ago
I'll try adding the function into the current page for now, and if I get that to work i'll try and refactor it later, as I'm not the best at react still lol