The difference between onBlur vs onChange for React text inputs

When is one called versus the other?

Is there a situation where onChange would be called but onBlur would not be called?

Which one should you use to update React state?

Do they behave differently?

Let me see if I can answer these questions for you.

I’ll start off by showing you how each one of these events behave, and get triggered.

What is onBlur event in React

React onBlur behaves just like the native JavaScript version of blur.


<input id="foo">

<script>
  const el = document.querySelector("foo");

  el.addEventListener("blur", () => {
    console.log("blur event");
  });
</script>

Every time you get out of focus from the input field, the event will trigger.

Here’s how it looks like in React


function App() {
  const [fieldValue, setFieldValue] = React.useState('');

  const handleBlur = (e) => setFieldValue(e.target.value);

  console.log(fieldValue);

  return <input onBlur={handleBlur} />;
}

It doesn’t matter if the value has changed or not, every time you get out of focus. The event will trigger.

What is onChange event in React

Does React onChange behave like it’s vanilla JavaScript version?

Nope.


<input id="foo">

<script>
  const el = document.querySelector("foo");

  el.addEventListener("change", () => {
    console.log("change event");
  });
</script>

In the vanilla version, it sort of behaves like the blur event. It gets triggered after you’re out of focus from the input field.

The difference is, it ONLY triggers when the value is different.

So how does React onChange behave?

React onChange gets triggered on every keystroke on the keyboard.


function App() {
  const [fieldValue, setFieldValue] = React.useState("");

  const handleChange = (e) => setFieldValue(e.target.value);

  console.log(fieldValue);

  return <input onChange={handleChange} />;
}

Whether the value is different or not, it will get triggered.

onBlur or onChange? Why not both?

It depends.

It really depends on what type of user experience you want to give.

Perhaps onChange would be a nice experience to give them a real-time update.

For example, let them know if they entered an invalid email address as they’re typing.


const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

function App() {
  const [email, setEmail] = React.useState({
    error: false,
    value: ""
  });

  const handleChange = (e: any) => {
    // Trim value & convert to lowercase
    const value = e.target.value.trim().toLowerCase();

    // Test if email is valid
    const isValidEmail = re.test(value);

    setEmail({
      value,
      error: !isValidEmail
    });
  };

  return (
    <>
      <input placeholder="Email" onChange={handleChange} />
      {email.error && <p>Please enter a valid email address.</p>}
    </>
  );
}

React is fast. You don’t have to worry about performance being an issue.

You’re not limited to just using one, you can always use them as a combination.


const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

function App() {
  const [email, setEmail] = React.useState({
    error: false,
    value: ""
  });
  const [showError, setShowError] = React.useState(false);

  const handleChange = (e: any) => {
    // Trim value & convert to lowercase
    const value = e.target.value.trim().toLowerCase();

    // Test if email is valid
    const isValidEmail = re.test(value);

    setEmail({
      value,
      error: !isValidEmail
    });

    // Hide error message if fixed.
    if (showError && isValidEmail) {
      setShowError(false);
    }
  };

  const handleBlur = () => {
    if (!email.error) {
      // Send an API request to check if email is already taken.
      alert("Checking if email is valid. One moment...");
    } else {
      setShowError(true);
    }
  };

  return (
    <>
      <input placeholder="Email" onChange={handleChange} onBlur={handleBlur} />
      {showError && <p>Please enter a valid email address.</p>}
    </>
  );
}

In the example above, I added a API call to check if the email address has been taken or if it’s available.

The API call is done on the onBlur event, that way I’m not hitting my servers on every keystroke.

Conclusion

Use React onChange if you want to give your users a real-time experience or to update React state.

Use React onBlur if you want to execute code after they’re out of focus or make API calls.

I like to tweet about React and post helpful code snippets. Follow me there if you would like some too!