How to change multiple properties of a state in react (at the same time)?

31,566

Solution 1

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

Solution 2

you can change multiple properties of a state like this.

this.setState({ openedCard: null, offeredChips: 0, activePlayer: nextPlayer });
Share:
31,566
catandmouse
Author by

catandmouse

I'm a front-end developer.

Updated on November 05, 2020

Comments

  • catandmouse
    catandmouse over 3 years

    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()?

  • GD- Ganesh Deshmukh
    GD- Ganesh Deshmukh about 4 years
    Upvoted for very helpful information as: Its okay to call multiple setStates since React internally does batching before setState and hence will only call render once.