user18923197
user18923197

Reputation:

Updating an object value in nested array React

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
    })
  }
  
 }

Upvotes: 1

Views: 794

Answers (1)

pilchard
pilchard

Reputation: 12911

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)
  })
}

Upvotes: 1

Related Questions