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.

First, if you’re looking to become a strong and elite React developer within just 11 modules, you might want to look into Wes Bos, Advanced React course for just $97.00 (30% off). Wouldn’t it be nice to learn how to create end-to-end applications in React to get a higher paying job? Wes Bos, Advanced React course will make you an elite React developer and will teach you the skillset for you to have the confidence to apply for React positions.

Click here to become a strong and elite React developer: Advanced React course.

Disclaimer: The three React course links are affiliate links where I may receive a small commission for at no cost to you if you choose to purchase a plan from a link on this page. However, these are merely the course I fully recommend when it comes to becoming a React expert.

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!