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.

You might try this


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 comment
Jack

Thanks for this.

Anonymous

hi jack

Anonymous

didnt work for me

JJ

Nice, worked for me. Could you perhaps elaborate on why onBlur works, and what is the actual use case for onBlur? Thank you!

AJ Farkas

Good write-up. You can clean up the code even more by removing `.bind(this)`: `this` always refers to the React component here.

RnMss

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) { ... }".

Sergei Gribovskii

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.

Anonymous

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/

vlakov

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/
---

Anonymous

Thanks, It work for me

Anonymous

Thanks a lot , it worked for me

liuzhigang

works for me.

Jeveen Shrestha

Thanks, it works for me.

Mike Rehy

saved my form! thanks

Roman Stejskal

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!

Yacoub Oweis

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;
}

Meow Woof

return false doesn't have an effect here; this isn't jQuery

Andreas Susilo

Thanks. It works!

Spiryt Sista

Thanks!

Anoop John

Thanks... this helped immensely!!

Anonymous

THanks!!

Gerald

Thanks, was a huge help!

ketan

Using **defaultValue** attribute worked for me in case of onblur.

Thuc Tran Van

Thank you so much

huashiyiqike

onBlur handler should compare content to make sure it really changed.

Anonymous

Ooooo maiiii gooooshhh, didn't realized this, awesomeee man, thanks a lot!

thang thang

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.

Ganesh Shetty

The best article on onChange
Nice explanation , really helped me
Write more articles like this

Your email will never ever be published.

Related posts

Go to top of the page