反应形式onChange-> setState落后一步

Kei*_*ong 41 javascript reactjs

我在构建webapp时遇到了这个问题,我在这个jsfiddle中复制了它.本质上,我想在this.setState({message: input_val})每次输入内容时调用一个输入,然后将其传递给父App类,然后将该消息重新呈现到Message类.然而,输出似乎总是落后于我实际输入的一步.jsfiddle演示应该是自我解释的.我想知道我是否做错了提示这一点.

HTML

<script src="http://facebook.github.io/react/js/jsfiddle-integration.js"></script>
<div id='app'></div>
Run Code Online (Sandbox Code Playgroud)

JS

var App = React.createClass({
    getInitialState: function() {
        return {message: ''}
    },
    appHandleSubmit: function(state) {
        this.setState({message: state.message});
        console.log(this.state.message);
    },
    render: function() {
        return (
            <div className='myApp'>
            <MyForm onChange={this.appHandleSubmit}/>
            <Message message={this.state.message}/>
            </div>
        );
    }
});

var MyForm = React.createClass({
    handleSubmit: function() {
        this.props.onChange(this.state);
    },
    handleChange: function(e) {
        console.log(e.target.value);
        this.setState({message: e.target.value});
        this.handleSubmit();
    },
    render: function() {
        return (
            <form className="reactForm" onChange={this.handleChange}>
            <input type='text' />
            </form>
        );
    }
});

var Message = React.createClass({
    render: function() {
        return (
            <div className="message">
                <p>{this.props.message}</p>
            </div>
        )
    }
});

React.render(
    <App />,
    document.getElementById('app')
);
Run Code Online (Sandbox Code Playgroud)

Wir*_*rie 45

呼叫setState不同步.它创建了"待定状态转换".(有关详细信息,请参见此处).您应该明确地将新input值作为要引发的事件的一部分传递(例如handleSubmit在您的示例中).

这个例子.

handleSubmit: function(txt) {
    this.props.onChange(txt);
},
handleChange: function(e) {
    var value = e.target.value;
    this.setState({message: value});
    this.handleSubmit(value);
},
Run Code Online (Sandbox Code Playgroud)


RC-*_*dan 27

有一个更简单的方法,这setState(updater, callback)是一个异步函数,它将回调作为第二个参数,

只需将handleSubmit作为回调传递给setState方法,这样在setState完成后,只会执行handleSubmit.

例如.

handleChange: function(e) {
    console.log(e.target.value);
    this.setState({message: e.target.value}, this.handleSubmit);
}
Run Code Online (Sandbox Code Playgroud)

尝试更改上面的handleChange()方法,它将工作.

使用setState的语法检查此链接


Tay*_*ach 8

因为这个,我拉了一个小时的头发,所以我决定分享......如果你的回调仍然落后一步并且似乎不起作用,请确保你不要用括号调用该函数......只需传递它in.菜鸟错误。

对:

handleChange: function(e) {
    console.log(e.target.value);
    this.setState({message: e.target.value}, this.handleSubmit);
}
Run Code Online (Sandbox Code Playgroud)

VS

错误的:

handleChange: function(e) {
    console.log(e.target.value);
    this.setState({message: e.target.value}, this.handleSubmit());
}
Run Code Online (Sandbox Code Playgroud)


小智 8

带有 setState 钩子

useEffect(() => {
    your code...
}, [yourState]);
Run Code Online (Sandbox Code Playgroud)

  • 您能扩展这个答案吗? (3认同)

Bri*_*and 5

MyForm 没有理由在这里使用状态。还将 onChange 放在表单上而不是您感兴趣的输入上很奇怪。受控组件应该是首选,因为它们的行为更明显,并且任何时候 App 的消息状态发生变化(即使您例如允许 Message 稍后更改它),它在任何地方都是正确的。

这也使您的代码更短,并且相当简单。

var App = React.createClass({
    getInitialState: function() {
        return {message: ''}
    },
    appHandleSubmit: function(message) {
        this.setState({message: message});
    },
    render: function() {
        return (
            <div className='myApp'>
                <MyForm onChange={this.appHandleSubmit} 
                        message={this.state.message} />
                <Message message={this.state.message}/>
            </div>
        );
    }
});

var MyForm = React.createClass({
    handleInputChange: function(e){
        this.props.onChange(e.target.value);
    },
    // now always in sync with the parent's state
    render: function() {
        return (
            <form className="reactForm">
                <input type='text' onChange={this.handleInputChange}
                       value={this.props.message} />
            </form>
        );
    }
});
Run Code Online (Sandbox Code Playgroud)

jsbin