1

I am trying to update a value within the state object of a React App. I am able to change the status string but I can't seem to figure out how to access the hp key for each fighter - I've tried different ways (I've written 2 in this example) without any success. What is the proper way of accessing the key of each fighter when you have an array with nested objects?

export default class App extends Component {
 state = {
  status: 'Fighters are Ready...',

   fighters: [
     {
       name: 'Fighter 1',
       hp: 150,
       image: ''
     },
     {
       name: 'Fighter 2',
       hp: 150,
       image: ''
     }
   ]
 }

 handleClick = (e) => {
  // console.log(e)
  if (e.target.name === 'Fighter 1') {
    this.setState({
       hp : this.state.fighters[1].hp - 10,
      status: e.target.name + ' is attacking ' + this.state.fighters[1].name
    })
  } else {
    this.setState({
      [Object.keys(this.state.fighters)[0].hp] : this.state.fighters[0].hp - 10,
      status: e.target.name + ' is attacking ' + this.state.fighters[0].name
    })
  }
  
 }

1 Answers1

1

You need to be sure to return an object of the same shape as the original state, while also avoiding mutation. Here spreading the current state into a new object, updating the status string as you were and then using a map() call to iterate over the fighters array and update the fighter that matches the event.target.

handleClick = (e) => {
  // console.log(e)
  this.setState({
    ...this.state,
    status: e.target.name + ' is attacking ' + this.state.fighters.find(f => f.name !== e.target.name)?.name,
    fighters: this.state.fighters.map(fighter =>
      fighter.name !== e.target.name
        ? ({ ...fighter, hp: fighter.hp - 10 })
        : fighter)
  })
}
pilchard
  • 12,414
  • 5
  • 11
  • 23
  • 1
    Nice answer! I understand most, except for one thing - what does the ? mean after the find parenthesis? (If I remove/leave it still works) - I have never seen this before - Thanks for your help! –  Jun 04 '22 at 01:02
  • 1
    It's [optional chaining (?.)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) which just saves it from throwing an error if the `find()` doesn't return an object. I threw it in for safety, but given your stable state it should work fine without it. – pilchard Jun 04 '22 at 01:03