Визуализация вызывается до состояния обновлений setState - PullRequest
1 голос
/ 14 марта 2019

Есть ли способ убедиться, что render вызывается после того, как setState действительно обновляет состояние?Насколько мне известно, setState является асинхронным.Я попытался указать render в качестве обратного вызова для setState, но он все еще отображается до обновления состояния.

HTML-код:

<div id="root"></div>

Код ответа:

class Table extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            squares: []
        };
        this.create = this.create.bind(this);
    }

    create() {
        console.log('squares before: ' + this.state.squares);
        var a = [];
        for (var i = 0; i < 16; i++) {
            a.push(undefined);
        }
        i = Math.floor(Math.random() * 8);
        a[i] = 2;
        i = Math.floor(Math.random() * 8) + 8;
        a[i] = 2;
        console.log('new squares: ' + squares);
        console.log('non-updated squares: ' + this.state.squares);
        this.setState({
            squares: a
        }, console.log('updated squares: ' + this.state.squares);
    }

    componentWillMount() {
        this.create();
    }

    render() {
        console.log('rendering');
        return (<div>
                <table className="table">
                    <tbody>
                        <tr>
                            <td className="td"><Number number={this.state.squares[0]}/></td>
                            <td className="td"><Number number={this.state.squares[1]}/></td>
                            <td className="td"><Number number={this.state.squares[2]}/></td>
                            <td className="td"><Number number={this.state.squares[3]}/></td>
                        </tr>
                        <tr>
                            <td className="td"><Number number={this.state.squares[4]}/></td>
                            <td className="td"><Number number={this.state.squares[5]}/></td>
                            <td className="td"><Number number={this.state.squares[6]}/></td>
                            <td className="td"><Number number={this.state.squares[7]}/></td>
                        </tr>
                        <tr>
                            <td className="td"><Number number={this.state.squares[8]}/></td>
                            <td className="td"><Number number={this.state.squares[9]}/></td>
                            <td className="td"><Number number={this.state.squares[10]}/></td>
                            <td className="td"><Number number={this.state.squares[11]}/></td>
                        </tr>
                        <tr>
                            <td className="td"><Number number={this.state.squares[12]}/></td>
                            <td className="td"><Number number={this.state.squares[13]}/></td>
                            <td className="td"><Number number={this.state.squares[14]}/></td>
                            <td className="td"><Number number={this.state.squares[15]}/></td>
                        </tr>
                    </tbody>
                </table>
            </div>);
    }
}

class Game extends React.Component {
    newGame() {
        this.refs.table.create();
    }

    render() {
        return (<div>
            <Table ref="table"/>
            <button id="newGame" onClick={this.newGame.bind(this)}>New Game</button>
        </div>);
    }
}

По сути, в этом случае сначала регистрируется «рендеринг», а затем «обновляются квадраты: ...» следующим образом:

squares before: [undefined, 2, undefined, undefined, undefined, 2]
new squares: [undefined, undefined, 2, undefined, 2, undefined]
non-updated squares: [undefined, 2, undefined, undefined, undefined, 2]
rendering
updated squares: [undefined, undefined, 2, undefined, 2, undefined]

Я попытался сделать обратный вызов setStaterender, но второй рендер будет отображаться после первого рендера, но до setState updated state:

this.setState({
  squares: a
}, this.render);

В нем записано:

squares before: [undefined, 2, undefined, undefined, undefined, 2]
new squares: [undefined, undefined, 2, undefined, 2, undefined]
non-updated squares: [undefined, 2, undefined, undefined, undefined, 2]
rendering
rendering

Любая помощь будет оченьоценили.Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 14 марта 2019

A synchronous setState в componentWillMount не вызывает повторный рендеринг, а отражает изменение самого начального рендеринга. Однако обратный вызов setState вызывается после метода рендеринга.

Если вы зарегистрируете state squares в методе рендеринга, он запишет правильный результат в самом начальном рендере.

PS componentWillMount устарела впоследние версии и лучше иметь вашу текущую логику в конструкторе вместо componentWillMount

Рабочая демонстрация

0 голосов
/ 14 марта 2019

используйте shouldComponentUpdate (объект nextProps, объект nextState), для рендеринга, каждый раз, когда он возвращает true, рендеринг будет происходить

...