I have this state in my main parent component:
this.state = {
playableCards: [],
openedCard: null,
offeredChips: 0,
activePlayer: 0, // first player is 0, second player is 1
players: [
{
name: "player1",
remainingChips: 11,
cards: [],
score: null
},
{
name: "player2",
remainingChips: 11,
cards: [],
score: null
}
]
};
Now, I have some methods that change different properties of the state. E.g.:
takeCard = () => {
const {
activePlayer,
players,
playableCards,
offeredChips,
openedCard
} = this.state;
if(openedCard) {
// Add card to active player
let playersClone = [...players];
playersClone[activePlayer].cards = [
...playersClone[activePlayer].cards,
openedCard
];
// Add any offered chips to active player
playersClone[activePlayer].remainingChips += offeredChips;
this.setState({ players: playersClone }, () =>
this.calculateScore(activePlayer)
);
// Remove card from deck
this.setState({
playableCards: playableCards.filter(function(card) {
return card !== openedCard;
})
});
// Change active player
const nextPlayer = activePlayer === 0 ? 1 : 0;
this.setState({ activePlayer: nextPlayer });
// Reset offered chips to 0
this.setState({ offeredChips: 0 });
// Reset opened card
this.setState({ openedCard: null });
} else {
console.log("Open a card first!");
}
};
As you can see, there are many properties that are being changed just by a single click event (this method is attached to a click event). I am wondering whether is this the proper way of doing it or should I combine all the setState()
?
Answer. Yes, you can use this. setState to change single, multiple, or even all properties of state at a time.
To update nested properties in a state object in React: Pass a function to setState to get access to the current state object. Use the spread syntax (...) to create a shallow copy of the object and the nested properties. Override the properties you need to update.
React is highly efficient and thus uses asynchronous state updates i.e. React may update multiple setState() updates in a single go. Thus using the value of the current state may not always generate the desired result.
Its okay to call multiple setStates since React internally does batching before setState and hence will only call render
once. That said, the chances of you making a mistake in writing setState such that batching ignores a change or sets incorrect value are high(for instance you may call setState twice for the same key based on the previous value and might expect a result different from what you get). Hence its recommended that you call setState once after processing all the values
// Add card to active player
let playersClone = [...players];
playersClone[activePlayer].cards = [
...playersClone[activePlayer].cards,
openedCard
];
// Add any offered chips to active player
playersClone[activePlayer].remainingChips += offeredChips;
const playableCards = playableCards.filter(function(card) {
return card !== openedCard;
})
// Change active player
const nextPlayer = activePlayer === 0 ? 1 : 0;
// Reset offered chips to 0
// Reset opened card
// Remove card from deck
this.setState({
openedCard: null,
offeredChips: 0,
playableCards,
players: playersClone
}, () =>
this.calculateScore(activePlayer)
);
you can change multiple properties of a state like this.
this.setState({ openedCard: null, offeredChips: 0, activePlayer: nextPlayer });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With