React update item quantity in the shopping cart - reactjs

I'm trying to update the quantity of each item , i have tried my code but it didn't work correctly, but when i tried a solution found here: How to update item quantity in the shopping cart using React Redux , it worked thankfully .
But i want to understand why my code didn't work (i'm using useContext not redux but normally that has nothing to do with the problem )
**Code that worked : ** :
cartItems: state.cartItems.map(item => item.id === payload.id
? {
...item,
qty: item.qty + 1,
}
: item
),
**My unfunctional code : **
if (productsInCard.find((x) => x.name === e.name)) {
let qu ; //to get the new quantity
const arr = [...productsInCard];
productsInCard.forEach((ele, index) => {
if (ele.name === e.name) {
qu = ele.quantity + 1;
console.log(ele.quantity + " this is the quantity before +1")
arr.splice(index, 1);
addCard(arr);
console.log("old item deleted" + JSON.stringify(arr))
addCard([
...productsInCard,
{
name: e.name,
price: e.price,
image: e.images[0],
quantity: qu,
},
]);
addCard([
...productsInCard,
{
name: e.name,
price: e.price,
image: e.images[0],
quantity: qu,
},
]);
console.log(" item + quantity added : " + JSON.stringify(productsInCard));
}
});
const newArr = [...productsInCard]
productsInCard.forEach((ele, index)=>{
if(ele.name === e.name){
console.log(ele.quantity)
if (ele.quantity < qu)
newArr.splice(index, 1)
addCard(newArr);
}
})
} else {
addCard([
...productsInCard,
{
name: e.name,
price: e.price,
image: e.images[0],
quantity: 1,
},
]);
console.log("list with new item : " + productsInCard);
}
}

Related

React useReducer() fired twice , always add double quantity to shopping cart?

In strict Mode, React runs twice to detect side effects. So I think I should not turn the strict Mode off, I should make sure that when running twice, the output still correct.
There is a product , when I add qty 3, run twice , the output will be 1 + 3 + 3 = 7.
It's a simple cart logic. When no item ,create an item and concat() it. It there is this item (qty>1 or findIndex() > 0), find it ,and edit its quantity. However, when run twice, add quantity will run twice too. How can I solve the problem?
export const CartContextProvider = props => {
const defaultCart = { items: [], qty: 0, total: 0 }
const cartReducer = (state, actions) => {
if (actions.type === 'SUBMIT') {
const [id, qty, price] = [
actions.item.id,
actions.item.qty,
actions.item.price
]
//ckeck if pd already exists
const itemIndex = state.items.findIndex(el => {
return el.id === id
})
// if no item ,add first item to cart
if (itemIndex === -1 && +qty > 0) {
const newItem = {
id: id,
qty: +qty,
price: +price
}
const updatedItems = state.items.concat(newItem)
const updatedQty = state.qty + +qty
const updatedTotal = state.total + +qty * +price
console.log(newItem.qty)
return { items: updatedItems, qty: updatedQty, total: updatedTotal }
} else {
console.log('run')
let findItem = state.items[itemIndex]
const updatedItem = {
id: id,
qty: findItem.qty + +qty, // here will run twice.
price: +price
}
const stateItems = state.items
stateItems[itemIndex] = updatedItem
console.log(updatedItem.qty)
const updatedQty = state.qty + +qty
const updatedTotal = state.total + +qty * +price
return { items: stateItems, qty: updatedQty, total: updatedTotal }
}
}
return defaultCart
}
const [cart, dispatchCart] = useReducer(cartReducer, defaultCart)
function cartSubmitHandler (id, qty, price) {
dispatchCart({ type: 'SUBMIT', item: { id: id, qty: qty, price: price } })
}
return (
<CartContext.Provider
value={{
cart: cart,
cartSubmitHandler: cartSubmitHandler
}}
>
{props.children}
</CartContext.Provider>
)
}
export default CartContext
The culprit is
const stateItems = state.items
should be :
const stateItems = [...state.items]
I slightly change the name of variables. Final code is presenting down below.

Replacing value in nested state with react functional components

I am trying to use update state in a react function component but it is not working. I tried following a tutorial on pluralsite and apply it to my own project. Ideally this code should be finding the product based on the ID number and replacing the total with a new value.
Unfortunately I am getting an error saying that 'productData.find' is not a function and I'm not sure where the code being used for that is. Are there any suggestions on how to solve this issue?
This is what the data looks like. In this example I am saving the first element of the array.
export let data = [
{
name: "Name",
description:
"",
products: [
{
id: 1,
name: "Name 1",
material: 1.05,
time: 25,
total: 0,
},
{
id: 2,
name: "Name 2",
material: 3,
time: 252,
total: 0,
},
],
},
...
];
function CompareCard({}) {
const index = 0;
const [productData, setProductData] = useState(data[index]);
function setTotalUpdate(id) {
const productPrevious = productData.find(function (rec) {
return rec.id === id;
});
const productUpdated = {
...productPrevious,
total: 1,
};
const productNew = productData.map(function (rec) {
return rec.id === id ? productUpdated : rec;
});
setProductData(productNew);
}
setTotalUpdate(1)
}
It's because productData is not an array so .find would not work. You want iterate over the products property in your data, so do productData.products.find(...)
When you do
const [productData, setProductData] = useState(data[index])
you don't pass an Array on your state but an Object (the first element of your data so an Object) and Object don't have find method.
Try
const [productData, setProductData] = useState([data[index]])
with [] on our useState to put your Object on array
///////////////////////////////// Edit /////////////
Ok, I try your code, and I propose you this.
import React, { useState } from "react";
const data = [
{
name: "Name",
description: "",
products: [
{
id: 1,
name: "Name 1",
material: 1.05,
time: 25,
total: 0,
},
{
id: 2,
name: "Name 2",
material: 3,
time: 252,
total: 0,
},
],
},
];
const CompareCard = () => {
// setState with the subArray products from data[0], I use '...' (spread operator) inside a Array or an Object to make a shalow copy
const [productsData, setProductsData] = useState([...data[0].products]);
const setTotalUpdate = (id) => {
// find the product to change inside products collection, that's ok
const productPrevious = productsData.find((rec) => {
return rec.id === id;
});
// create a new product to change one property's value, you can do something like 'productPrevious.total = 1', same same
const productUpdated = {
...productPrevious,
total: 1,
};
// create a new products collection to update state
const productNew = productsData.map((rec) => {
return rec.id === id ? productUpdated : rec;
});
setProductsData([...productNew]);
};
const setTotalUpdateSecond = (id) => {
// create a newState
const newState = productsData.map((product) => {
// condition if id === productId and do something
if (id === product.id) {
product.total = 1;
}
// both case, I return the product (change or not)
return product;
});
setProductsData([...newState]);
};
return (
<>
<button onClick={() => setTotalUpdate(1)}>Test old method on product 1</button>
<button onClick={() => setTotalUpdateSecond(2)}>Test second method on product 2</button>
{productsData.map((product) => {
return (
<>
<p>Product Id : {product.id} / Product Total : {product.total}</p>
</>
);
})}
</>
);
};
export default CompareCard;
Can you copy / past this, try and say me if it's what you want, if yes, I explain you where the confusion was. If not, explain me, what's the problem here and I modificate.

Need to add quantity on my react state object

I am stuck with a problem where I am updating React state with an array of objects where my original object is like this.
[{id:"123", name:"Product 1"}, {id:"456", name:"Product 2"}];
Suppose this is an e-commerce cart list, where now if I add the same product again, being 'id' property as unique for each product it should increase the quantity of that product.
I need this [[{id:"123", name:"Product 1 , quantity: 2"}, {id:"456", name:"Product 2"}];]
Instead I am getting state like this,
[{id:"123", name:"Product 1"}, {id:"456", name:"Product 2"},{id:"123", name:"Product 1"} ];
I do not want that third item on my array, I want it to increase the quantity property which is also not available on the object before.
I am using React hooks on this
Please do help. Thanks in advance.
You need to find the index of the item inside the cart array based on the id and then update the quantity, or set it to 1 as initial value.
I added a small sample but you can adapt it to hooks code.
let cart = [{id:"123", name:"Product 1"}, {id:"456", name:"Product 2"}];
let newCart = JSON.parse(JSON.stringify(cart))
let index = newCart.findIndex(obj => obj.id === "123")
if (index >= 0) {
newCart[index].quantity = (newCart[index].quantity | 0) + 1
}
console.log(newCart)
I tried this after posting the question and it worked.
const addToCart = (productToAdd) => {
const present = cartItem.some((prod) => {
return prod.id === productToAdd.id;
});
if (!present) {
productToAdd["quantity"] = 1;
setcartItem((prev) => {
return [...prev, productToAdd];
});
} else {
setcartItem((prev) => {
prev.map((prod) => {
if (prod.id === productToAdd.id) {
prod.quantity++;
}
});
return [...prev];
});
}
};
Use map() to iterate through existing state and update the object when id matches to the input.
const state = [
{ id: "123", name: "Product 1" },
{ id: "456", name: "Product 2" },
];
setState = (_state) =>
state.map((item) =>
item.id === _state.id
? { ...item, quantity: item["quantity"] + 1 || 2 }
: item
);
const newState = setState({ id: "123", name: "Product 1" });
console.log(newState);

React: Find if there's duplicate value into array then increment only the specific key value of the object

I'm creating this component that will add item into the cart. The output that I want if the user add a duplicate value there's a specific key value name noOfOrder that will be incremented. My array will be stored in localStorage.
LocalStorage
0: {title: "Spicy Ramen",…}
description: "The perfect hybrid of fancy restaurant-style ramen and the pre-packaged instant noodles."
noOfOrders: 1
price: 17
title: "Spicy Ramen"
1: {title: "Spicy Chicken",…}
description: "Sweet and Spicy Chicken is perfectly crispy and coated in the most delicious, sweet, sti"
noOfOrders: 1
price: 4
title: "Spicy Chicken"
UseState
const [checkOutItems, setCheckOutItems] = useState(
JSON.parse(localStorage.getItem('CheckOutItem')) || []
);
AddToCart Function
const handleAddToCart= () => {
let oldArrays = JSON.parse(localStorage.getItem('CheckOutItem')) || [];
let itemArrays = {
title: itemInfo.title,
description: itemInfo.description,
price: itemInfo.price * noOfItem || itemInfo.price,
noOfOrders: 1,
};
if (oldArrays.some((item) => item.title === itemArrays.title)) {
const match = oldArrays.findIndex(
(product) => product.title === itemArrays.title
);
if (match) {
match.noOfOrders++;
}
oldArrays[oldArrays.findIndex((el) => el.title === match.title)] = match;
localStorage.setItem('CheckOutItem', JSON.stringify(oldArrays));
} else {
setCheckOutItems((prev) => [...prev, itemArrays]);
oldArrays.push(itemArrays);
}
localStorage.setItem('CheckOutItem', JSON.stringify(oldArrays));
};
Thanks!
This will mutate the products so make sure it's a clone or if you parsing from localstorage then you don't really need to clone as this object is created
const key = 'cart'
const products = JSON.parse(localStorage.getItem(key)) || [];
const match = products.find(product => product.id === id);
if (match) {
match.count++;
}
localStorage.setItem(key, JSON.stringify(products));

Got a parsing error while assign a value on my state

Hi friends,
I'm getting a little trouble putting that to work.
This method intend to put check if there's a product in the cart, if true, sum the same product.
onAddProductToCart = (productId) => {
const productInCart = this.state.productsInCart.find(
(product) => productId === product.id
);
if (productInCart) {
const newProductsInCart = this.state.productsInCart.map(product => {
if(productId === product.id) {
return {
...product,
quantity = product.quantity + 1
}
}
return product
})
this.setState({productsInCart: newProductsInCart})
}
};
I'm getting this error point to my assignment "=" bellow
Parsing error unexpected token:
quantity = product.quantity + 1
This method is inside the App class component , with has some mocked data.
class App extends Component {
state = {
minFilter: "100",
maxFilter: "2000",
nameFilter: "Produto",
productsInCart: [
{
id: 3,
name: "Produto 3",
price: 300.77,
photo: "https://picsum.photos/200/200?a=3",
quantity: 1,
},
{
id: 4,
name: "Produto 4",
price: 400,
photo: "https://picsum.photos/200/200?a=4",
quantity: 2,
},
],
};
You have to use colon : when set a object property
return {
...product,
quantity:product.quantity + 1
}
Using a colon would do the trick
quantity: product.quantity + 1

Resources