DEV Community

Anunoy Dussa
Anunoy Dussa

Posted on

React useState Help - Update item in Array of Objects

Hello,

I'm creating a game where you have to roll ten dice and get their numbers to match. You can reroll the dice and you can click on a die to freeze it (keep it's number/don't reroll)

I'm storing dice data in a useState that holds an array of objects

When I try to update the useState object by directly reversing the die's isFrozen boolean, it doesn't work. Instead, it works when I make a copy of the die object, update it, and return it

I don't understand why I can't directly update the die object in the array. Why do I have to create a copy of the die object?

useState

 const [dice, setDice] = useState(() => { const diceArray = []; for (let i = 1; i <= 10; i++) { diceArray.push({ id: nanoid(), num: rollDice(), isFrozen: false }); } return diceArray; }); 
Enter fullscreen mode Exit fullscreen mode

freezeDie code - Doesn't work

 const freezeDie = (id) => { setDice((oldDice) => oldDice.map((die) => { if (die.id === id) { console.log("die", die); console.log(""); die.isFrozen = !die.isFrozen; // THIS LINE } return die; }) ); }; 
Enter fullscreen mode Exit fullscreen mode

Result

  • the first click reverses the isFrozen boolean (it freezes the die - intended)
  • future clicks reverses the isFrozen boolean twice (basically nothing changes - not intended)

Image description

freezeDie code - Works

 const freezeDie = (id) => { setDice((oldDice) => oldDice.map((die) => { if (die.id === id) { console.log("die", die); console.log(""); return { ...die, isFrozen: !die.isFrozen }; // THIS LINE } return die; }) ); }; 
Enter fullscreen mode Exit fullscreen mode

Result

  • the first click reverses the isFrozen boolean (it freezes the die - intended)
  • future clicks also reverse the isFrozen boolean but call the function twice (not sure why it's being called twice)

Image description

Top comments (0)