How to "onchange" in ReactJS

21 October 2015   23 comments   Javascript, ReactJS

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

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

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

Your email will never ever be published


Related posts

Previous:
And bash basics 16 October 2015
Next:
Weight of your PostgreSQL tables "lumped together" 31 October 2015
Related by Keyword:
10 Reasons I Love create-react-app 04 January 2017
How to deploy a create-react-app 04 November 2016
Visual speed comparison of AngularJS and ReactJS 20 July 2015
Careful when dealing with options in IE 14 April 2006
Related by Text:
jQuery and Highslide JS 08 January 2008
I'm back! Peterbe.com has been renewed 05 June 2005
Anti-McCain propaganda videos 12 August 2008
Ever wondered how much $87 Billion is? 04 November 2003
Guake, not Yakuake or Yeahconsole 23 January 2010