I encountered this problem building a webapp and I replicated it in this jsfiddle. Essentially, I would like an input to call this.setState({message: input_val})
every time I type something into it, then pass it into the parent App class which then re-renders the message onto the Message class. However the output seems to always be one step behind what I actually type. The jsfiddle demo should be self explanatory. I am wondering if I did anything wrong to prompt this.
html
<script src="http://facebook.github.io/react/js/jsfiddle-integration.js"></script> <div id='app'></div>
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') );
Advertisement
Answer
A call to setState
isn’t synchronous. It creates a “pending state transition.” (See here for more details). You should explicitly pass the new input
value as part of the event being raised (like to handleSubmit
in your example).
See this example.
handleSubmit: function(txt) { this.props.onChange(txt); }, handleChange: function(e) { var value = e.target.value; this.setState({message: value}); this.handleSubmit(value); },