Understanding React's preventdefault()

Posted on November 02, 2020


React has an internal event system that gets triggered every time a certain action is taken by the user. For example, an event can be triggered when you click on a button with the onClick prop:

function LogButton(){
  const handleClick = (event) => {
    console.log("Hello World!")
    console.log(event)
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  )
}

When you click on the button above, the event variable will be logged as a SyntheticBaseEvent object in your console:

React's SyntheticBaseEvent log
React's SyntheticBaseEvent log

The event argument passed into handleClick is React’s own Synthetic event. It will always get send into your event handler function.

React’s Synthetic events are basically wrappers around the native DOM events. They are helper functions created to make sure the events have consistent properties across different browsers.

These specific events are baked into React library to help you in creating the proper responses to a user’s actions. General use cases where you need to make use of these event handlers include listening to user inputs and storing form input data in React’s state.

But since Synthetic events are just wrappers, the internal default behavior of the DOM object will still be triggered. One problem with the native DOM events is that it sometimes triggers a behavior that you don’t need.

For example, a form’s submit button in React will always trigger a browser refresh to submit the data into a backend system. This is bad because the behavior you defined in the onSubmit event function will be ignored by the browser. Try the following example:

import React, { useState } from "react";

export default function App() {
  const [name, setName] = useState("");

  const handleSubmit = (event) => {
    console.log(name);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input
          type="text"
          value={name}
          onChange={(event) => setName(event.target.value)}
        />
      </label>
      <input type="submit" value="Submit" />
    </form>
  );
}

Because of the default DOM event behavior, the handleSubmit function will be ignored and your log will not get written on the console.

This may be good in the past where the entire form validation and processing happens in the backend, but modern web applications tend to run the form validation process on the client-side in order to save time and bandwidth. To do so, you need to run your own defined behavior.

To cancel the native behavior of the submit button, you need to use React’s event.preventDefault() function:

const handleSubmit = (event) => {
  event.preventDefault();
  console.log(name);
};

And that’s all you need. Now the default event behavior will be canceled, and any code you write inside handleSubmit will be run by the browser.

You can also write the preventDefault() function on the last line of your function:

const handleSubmit = (event) => {
  console.log(name);
  console.log("Thanks for submitting the form!");
  event.preventDefault();
};

But for collaboration and debugging purposes, it’s always better to write the prevent function just below your function declaration. That way you won’t cause a bug by forgetting to put the prevent function too.

More about React:

Level up your React skill today 🔥

Build FOUR projects using React with my latest book.

Structured knowledge from beginner to experienced level!

Learn more