简体   繁体   中英

How do I update the value of an object property inside of an array in React state

I cannot seem to find an answer on here that is relevant to this scenario.

I have my state in my React component:

this.state = {
    clubs: [
       {
           teamId: null,
           teamName: null,
           teamCrest: null,
           gamesPlayed: []
        }
    ]
}

I receive some data through API request and I update only some of the state, like this:

this.setState((currentState) => {
    return {
        clubs: currentState.clubs.concat([{
            teamId: team.id,
            teamName: team.shortName,
            teamCrest: team.crestUrl
        }]),
    }
});

Later on I want to modify the state value of one of the properties values - the gamesPlayed value.

How do I go about doing this? If I apply the same method as above it just adds extra objects in to the array, I can't seem to target that specific objects property. I am aiming to maintain the objects in the clubs array, but modify the gamesPlayed property.

Essentially I want to do something like:

clubs: currentState.clubs[ index ].gamesPlayed = 'something';

But this doesn't work and I am not sure why.

Cus you are using concat() function which add new item in array.

You can use findIndex to find the index in the array of the objects and replace it as required:

Solution:

 this.setState((currentState) => {
    var foundIndex = currentState.clubs.findIndex(x => x.id == team.id);
    currentState.clubs[foundIndex] = team;

    return clubs: currentState.clubs
});

I would change how your state is structured. As teamId is unique in the array, I would change it to an object.

clubs = {
  teamId: {
    teamName,
    teamCrest,
    gamesPlayed
  }
}

You can then update your state like this:

addClub(team) {
    this.setState(prevState => ({
      clubs: {
        [team.id]: {
          teamName: team.shortName,
          teamCrest: teamCrestUrl
        },
        ...prevState.clubs
      }
    }));
  }

  updateClub(teamId, gamesPlayed) {
    this.setState(prevState => ({
      clubs: {
        [teamId]: {
          ...prevState.clubs[teamId],
          gamesPlayed: gamesPlayed
        },
        ...prevState.clubs
      }
    }));
  }

This avoids having to find through the array for the team. You can just select it from the object.

You can convert it back into an array as needed, like this:

Object.keys(clubs).map(key => ({
  teamId: key,
  ...teams[key]
  }))

The way I approach this is JSON.parse && JSON.stringify to make a deep copy of the part of state I want to change, make the changes with that copy and update the state from there.

The only drawback from using JSON is that you do not copy functions and references, keep that in mind.

For your example, to modify the gamesPlayed property:

let newClubs = JSON.parse(JSON.stringify(this.state.clubs))

newClubs.find(x => x.id === team.id).gamesPlayed.concat([gamesPlayedData])

this.setState({clubs: newClubs})

I am assuming you want to append new gamesPlayedData each time from your API where you are given a team.id along with that data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM