Search code examples
reactjssetstatemutation

ReactJS - View not re-rendered after updating state using slice


This is my class Content which is rendered inside App.js. I have read through ReactJS tutorial and understand that I need to change data without mutation.

https://reactjs.org/tutorial/tutorial.html

But even when I use slice, the app does not re-render on state changes.

This class manage a deck of cards like below:

//omitted imports
import main_deck from ...
import side_deck from ...

export default class Content extends Component {
    constructor(props) {
        super(props);
        this.moveToMainDeck = this.moveToMainDeck.bind(this);
        this.state = {
            mainDeck : main_deck,
            sideDeck : side_deck
        }
    }

    moveToMainDeck(card) {
        const fromDeck = this.state.sideDeck.slice(); //copy the state data
        const toDeck = this.state.mainDeck.slice();

        var movable = checkMovability(fromDeck, toDeck, card);
        if (movable[0] === 1) { //use slice instead of splice
            var newMain = toDeck.slice(0, movable[1]).concat([card]).concat(toDeck.slice(movable[1]));

            var cardIndexInSideDeck = fromDeck.indexOf(card);
            var newSide = fromDeck.slice(0, cardIndexInSideDeck).concat(fromDeck.slice(cardIndexInSideDeck + 1));

            this.setState({ mainDeck : newMain, sideDeck : newSide });
        }
        else if (movable[0] === -1)
            alert("Unable to move. Main Deck is full.");
        else //movable[0] === 0
            alert("Unable to move. Limit reached for this card in Main Deck.");
    }

    render() {
        return (
            <div><MainDeck ... /><SideDeck ... /></div>
        );
    }
}

With the above code, I test the state data by printing out JSON array, the state does change after this.setState, but the view still does not re-render.

However, I tested by replacing slice() with push(), everything is re-rendered after state changes, like this: fromDeck.push(card); or toDeck.push(card);

Anyone please tell what is wrong with the slice I am using. Thanks a lot!


Solution

  • You could try using, as suggested here:

    const fromDeck = JSON.parse(JSON.stringify(this.state.sideDeck))
    

    This should create a completely new copy.