I have a state that returns an array of objects :
const [coins, setCoins] = useState([])
const [newCoins, setNewCoins] = useState([])
console.log(coins)
[
{
"note": "",
"quantity ": 2,
"name": "Bitcoin",
"price": 37000.98,
},
{
"note": "",
"name": "Bitcoin",
"quantity": 1,
"price": 37000.98,
},
{
"note": "",
"name": "Ethereum",
"price": 2690.32,
"quantity": 1,
}
]
I would like, starting from this list of objects, to create a new table in order to display a concise summary of the previous table. So you have to merge the objects with the same "name", cumul the "quantity", and finally add a new "key" which will be used to add the current price (retrieved via an API).
Using reduce works fine and returns me a new array
const coinsArrCopy = coins.map(item => ({...item}))
const coinsCopy = coinsArrCopy.reduce((acc, obj) => {
let existItem = acc.find(item => item.name === obj.name);
if (existItem) {
existItem.quantity = obj.quantity
delete existItem.price
delete existItem.note
return acc;
}
acc.push({...obj, currentPrice: 0})
// return setNewCoins(acc) <== ERROR
return acc;
}, [])
The new table looks like this:
console.log(coinsCopy)
[
{
"quantity": 3,
"name": "Bitcoin",
"currentPrice": 0
},
{
"name": "Ethereum",
"quantity": 1,
"currentPrice": 0
}
]
How to transfer this coinsCopy array to newCoins state? return setNewCoins(acc) gives me an error setNewCoins is not a function?
CodePudding user response:
You can call your setNewCoins function to update the state right after you've created the coinsCopy variable, as long as you're performing such calculation on the same component or on a child component (in this case you'll have to pass the setNewCoins function through props). You'll end up with something like:
const coinsArrCopy = coins.map(item => ({...item}))
const coinsCopy = coinsArrCopy.reduce((acc, obj) => {
let existItem = acc.find(item => item.name === obj.name);
if (existItem) {
existItem.quantity = obj.quantity
delete existItem.price
delete existItem.note
return acc;
}
acc.push({...obj, currentPrice: 0})
return acc;
}, [])
//This will update the state with the current value of the coinsCopy array.
setNewCoins(coinsCopy)
CodePudding user response:
The solution was actually quite simple.
You have to add the change of state in a useEffect, and listen to the "coins" state to restart the effect again when it detects a change.
useEffect(() => {
setNewCoins(coinsCopy)
}, [coins])
