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);
Related
Basically i want to select an emoji from an array which contains objects (id, name, count) and if i select an item on the array i want to increase its value and if i deselct it i want to decrease its value
for now i've done this which basically increase the value of an item in the array, please help me, thanks.
this is the array
const [emojisArr, setEmojisArr] = React.useState([
{
name: 'like',
emoji: '👍',
count: 11,
},
{
name: 'heart',
emoji: '❤️',
count: 21,
},
{
name: 'joy',
emoji: '😂',
count: 31,
},
{
name: 'fire',
emoji: '🔥',
count: 34,
},
{
name: 'star',
emoji: '💯',
count: 5,
},
]);
and this is the function when i click on the button
const likePost = item => {
const index = emojisArr.findIndex(emoji => emoji.name === item);
emojisArr[index].count += 1;
setEmojisArr(old => [...old]);
}
Set this code see below. you can pass action (selected/deselected) as string. so, it can increment/decrement count on the behalf of action.
const post = (item, action) => {
const newState = emojisArr.map((emoji) => {
if (emoji.name === item) {
return {
...emoji,
count: action === "selected" ? emoji.count + 1 : emoji.count - 1
};
}
return emoji;
});
setEmojisArr(newState);
};
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.
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));
I'm trying to add functionality to my application for deleting values in the list array of the following state
shoeList : [
{name: 'Nike',
list : [
{type: 'boots', revenue: '1000000', gender: 'mens', price: '49.99', id: 3},
{type: 'shoes', revenue: '13280100', gender: 'womens', price: '99.99', id: 2}
]
}
],
I understand that ids have to be equal in order for a deletion to occur. Right now i'm trying to access the appropriate row to be deleted(type, revenue, gender, and price) but am not sure how to access properties in an array thats within an array.
Here is the code i have so far
deleteShoe = (id) =>
{
let shoeList = this.state.shoeList.filter(shoe =>{
return (
shoe.list.filter(shoeid =>{
return shoeid.id !== id
}
)
)
});
this.setState({
shoeList: shoeList
})
}
Obviously this code doesn't and can't understand why. The only reason I can think of is that filter can't be nested but if so how would I go about implementing this. Any help would be great
You're close. You're just missing reassignment of shoe.list with updated list of shoes after filtering.
deleteShoe = (id) => {
const { shoeList } = this.state;
const newShoeList = shoeList.map(shoe => {
shoe.list = shoe.list.filter(shoeid => shoeid.id !== id)
return shoe;
});
this.setState({
shoeList: newShoeList
})
}
This should remove appropriate shoe id and reassign your shoe.list with newly filtered shoes list.
I'd like to update a state of one object in array, not updating the state of whole array.
const [users, setUsers] = useState;
const data = [
{
id: 1,
name: "John",
activeAccount: 1
},
{
id: 2,
name: "Mary",
activeAccount: 1
},
{
id: 3,
name: "Max",
activeAccount: 1
}
]
For example, John deactivate his account and state of activeAccount should be updated to 0.
So only one object should be updated (he has no data from other users and cannot update all array) - just example, why i use here user.id
const index = users.findIndex(obj => obj.id === user.id); // find index of object
users[index].activeAccount = 0
setUsers(users) // Nothing updated
I also tried to use Immutability Helper
import update from 'immutability-helper';
const index = users.findIndex(obj => obj.id === user.id); // find index of object
setUsers({
users: update(...users, {index: {activeAccount: {$set: 0 }}})
})
Could anyone help? Is there a solution?
Solution:
const index = users.findIndex(obj => obj.id === user.id);
setUsers([...users, users[index].activateAccount = 0])
There might be a problem in calling
setUsers({
users: update(...users, {index: {activeAccount: {$set: 0 }}})
})
In case you are initialising your state with:
const data = [
{
id: 1,
name: "John",
activeAccount: 1
},
{
id: 2,
name: "Mary",
activeAccount: 1
},
{
id: 3,
name: "Max",
activeAccount: 1
}
]
const [users, setUsers] = useState(data);
then you need to call setUsers without object:
setUsers(
update(...users, {index: {activeAccount: {$set: 0 }}})
)