React 不会立即改变状态

React doesn't chang state immediately

美好的一天。我有以下问题:我有一个 class 计算器,它会在单击按钮时更改 firstOperand 参数的状态。但是状态不会立即改变,只有当我再点击一个按钮时它才会改变 firstOperand 的状态。结果是延迟了 1 个操作:我点击了 1 - 指标没有改变,我点击了 2 - 指标变成了 1,我点击了 5 - 指标变成了 12,等等。 这是我的部分代码:

    var Indicator = React.createClass({

        render: function () {
            return (
                    <div className="calc-indicator">
                        <input id="indicator" type="text" maxLength="20" size="20" value={this.props.value}/>
                    </div>
            );
        }
    });


    var Button = React.createClass({

        render: function () {
            return (
                    <div className="nav-button">
                        <button type="button" id={this.props.identifier} onClick={this.props.clickHandler}>
                            {this.props.digit}
                        </button>
                    </div>
            );
        }
    });


    var Calculator = React.createClass({

        setFirstOperand: function (value) {
            this.setState(
                    {
                        firstOperand: value
                    }
            );
            if (isDebug) {
                console.log("First operand state is set to " + value + ".");
            }
        },

        setSecondOperand: function (value) {
            this.setState(
                    {
                        secondOperand: value
                    }
            );
        },

        changeIndicator: function (value) {
            if (isDebug) {
                console.log("///Change indicator method is working///");
                console.log("change indicator parameter is " + value);
                console.log("first operand is " + this.state.firstOperand);
                console.log("second operand is " + this.state.secondOperand);
                console.log("operation is " + this.state.operation);
            }
            if (!value) { // if value hasn't been gotten
                value = '';

                if (this.state.firstOperand) {
                    value += this.state.firstOperand;
                } else {
                    value = '0';
                }
                if (this.state.operation) {
                    value += this.state.operation;
                }
                if (this.state.secondOperand) {
                    value += this.state.secondOperand;
                }
            }
            this.setState(
                    {
                        value: value
                    }
            );
            if (isDebug) {
                console.log("indicator is changed to " + value);
                console.log("/////////////////////////////////////");
            }
        },

        getInitialState: function () {
            calculator = this;
            return {
                firstOperand: null,
                secondOperand: null,
                operation: null,
                divisionByZero: false,
                value: '0'
            };
        },

        cipherClicked: function (event) {

            if (this.state.divisionByZero) {
                this.setDivisionByZero(false);
            }
            var newValue = event.target.innerHTML;
            var firstValue = this.state.firstOperand;
            var secondValue = this.state.secondOperand;
            var operation = this.state.operation;

            if (operation) {
                if (secondValue) {
                    secondValue = secondValue + newValue;
                } else {
                    secondValue = newValue;
                }
                if (isDebug) {
                    console.log("Second operand state is setting to " + secondValue + ".");
                }
                this.setSecondOperand(secondValue);
            } else {
                if (firstValue) {
                    firstValue = firstValue + newValue;
                } else {
                    if (newValue != 0) { // if indicator contains 0 and you have tried to add one 0 more
                        firstValue = newValue;
                    }
                }
                if (isDebug) {
                    console.log("First operand state is setting to " + firstValue + ".");
                }
                this.setFirstOperand(firstValue);
                setOperand(firstValue);
            }
            if (isDebug) {
                console.log("Calling changeIndicator function.");
            }

            this.changeIndicator();
        },


        render: function () {

            return (
                    <div id="calculator">
                        <table>
                            <tr>
                                <td colSpan="4">
                                    <Indicator value={this.state.value} />
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="MC" digit="MC" clickHandler={this.memoryNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="MR" digit="MR" clickHandler={this.memoryNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="M+" digit="M+" clickHandler={this.memoryNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="M" digit="M" clickHandler={this.memoryNavigationClicked}/>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="BS" digit="BS" clickHandler={this.editNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="CL" digit="CL" clickHandler={this.editNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="C" digit="C" clickHandler={this.editNavigationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="negate" digit="+-" clickHandler={this.negateClicked}/>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="7" digit="7" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="8" digit="8" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="9" digit="9" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="divide" digit="/" clickHandler={this.operationClicked}/>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="4" digit="4" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="5" digit="5" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="6" digit="6" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="multiply" digit="*" clickHandler={this.operationClicked}/>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="1" digit="1" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="2" digit="2" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="3" digit="3" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="minus" digit="-" clickHandler={this.operationClicked}/>
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <Button identifier="0" digit="0" clickHandler={this.cipherClicked}/>
                                </td>
                                <td>
                                    <Button identifier="dot" digit="." clickHandler={this.dotClicked}/>
                                </td>
                                <td>
                                    <Button identifier="eq" digit="=" clickHandler={this.operationClicked}/>
                                </td>
                                <td>
                                    <Button identifier="plus" digit="+" clickHandler={this.operationClicked}/>
                                </td>
                            </tr>
                        </table>
                    </div>
            );
        }
    });

    React.render(<Calculator />, document.body);

</script>
</body>
</html>

根据我的 React Native 回答 setState 可以是异步操作,而不是同步操作。这意味着状态更新可以一起批处理,而不是立即完成,以获得性能提升。如果你真的需要在状态真正更新后做一些事情,有一个回调参数:

this.setState({ searchString: event.nativeEvent.text }, function(newState) {
    console.log('Changed State');
    console.log('searchString = ' + this.state.searchString);
}.bind(this));

React Documentation中也提到了。