Home > Mobile >  Return setState in reduce
Return setState in reduce

Time:02-04

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])
  •  Tags:  
  • Related