Normally, in vanilla Javascript, the onchange
event is triggered after you have typed something into a field and then "exited out of it", e.g. click outside the field so the cursor isn't blinking in it any more. This for example
document.querySelector('input').onchange = function(event) {
document.querySelector('code').textContent = event.target.value;
}
First of all, let's talk about what this is useful for. One great example is a sign-up form where you have to pick a username or type in an email address or something. Before the user gets around to pressing the final submit button you might want to alert them early that their chosen username is available or already taken. Or you might want to alert early that the typed in email address is not a valid one. If you execute that kind of validation on every key stroke, it's unlikely to be a pleasant UI.
Problem is, you can't do that in ReactJS. It doesn't work like that. The explanation is quite non-trivial:
*"<input type="text" value="Untitled">
renders an input initialized with the value, Untitled
. When the user updates the input, the node's value property will change. However, node.getAttribute('value')
will still return the value used at initialization time, Untitled
.
Unlike HTML, React components must represent the state of the view at any point in time and not only at initialization time."*
Basically, you can't easily rely on the input field because the state needs to come from the React app's state, not from the browser's idea of what the value should be.
var Input = React.createClass({
getInitialState: function() {
return {typed: ''};
},
onChange: function(event) {
this.setState({typed: event.target.value});
},
render: function() {
return <div>
<input type="text" onChange={this.onChange.bind(this)}/>
You typed: <code>{this.state.typed}</code>
</div>
}
});
React.render(<Input/>, document.querySelector('div'));
But what you notice is the the onChange
handler is fired on every key stroke. Not just when the whole input field has changed.
So, what to do?
The trick is surprisingly simple. Use onBlur
instead!
Same snippet but using onBlur
instead
var Input = React.createClass({
getInitialState: function() {
return {typed: ''};
},
onBlur: function(event) {
this.setState({typed: event.target.value});
},
render: function() {
return <div>
<input type="text" onBlur={this.onBlur.bind(this)}/>
You typed: <code>{this.state.typed}</code>
</div>
}
});
React.render(<Input/>, document.querySelector('div'));
Now, your handler is triggered after the user has finished with the field.