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.
Comments
Post your own commentThanks for this.
hi jack
didnt work for me
Nice, worked for me. Could you perhaps elaborate on why onBlur works, and what is the actual use case for onBlur? Thank you!
Good write-up. You can clean up the code even more by removing `.bind(this)`: `this` always refers to the React component here.
I don't think so. If you don't bind `this`, `this` would be the `event.target` ( the instance of <input> ).
Your case is probably because you always use the ES6 arrow function ( (args)=>{...} ), which treats `this` as a normal variable. This is unlike a classic anonymous "function (args) { ... }".
No, that's because React now binding it by itself. So You don't need to use it. And to say more you have to not use it. Not if you need to pass some params for example you need to type .bind(null, param1, param2). Just read the updated documentation of React.
Unless you are Using ES6 syntax where .bind(this) is needed. Using ES5 and older syntax, You do not need to .bind(this).
Reference: https://toddmotto.com/react-create-class-versus-component/
Thank you, very useful.
There are more wrong ways than there are good ways of using "this". It is ridiculous how simple things can be done the wrong way. Smart people devising new ways for stupids like me to shoot in the leg :-)).
---
https://daveceddia.com/avoid-bind-when-passing-props/
---
Thanks, It work for me
Thanks a lot , it worked for me
works for me.
Thanks, it works for me.
saved my form! thanks
Note that the native implementation (at least in Chrome) of `onChange` and `onBlur` is not the same!
`blur` only triggers once you click (or tab) out of the input (when the input loses focus), whereas `change` can also be triggered by hitting the Enter key!
You are absolutely right about the "Enter key", and this is very important in many cases to maintain a good user experience for the form elements. A simple solution to adopt the behavior of the Enter key is this code snip-it:
<input type="text" onBlur={this.onBlur} onKeyPress={this.handleEnterKeyPress} />
handleEnterKeyPress: function (e) {
if(e.which == 13){
e.target.blur();
}
return false;
}
return false doesn't have an effect here; this isn't jQuery
Thanks. It works!
Thanks!
Thanks... this helped immensely!!
THanks!!
Thanks, was a huge help!
Using **defaultValue** attribute worked for me in case of onblur.
Thank you so much
onBlur handler should compare content to make sure it really changed.
Ooooo maiiii gooooshhh, didn't realized this, awesomeee man, thanks a lot!
this work but it can create a bug, If the user Press Enter, it should handle something, but the input not blur yet and the state still not update then enter action will handle an old state.
The best article on onChange
Nice explanation , really helped me
Write more articles like this