Skip to main content

Common Events: `onSubmit` (Part 3) #44

📖 Introduction

We've learned how to handle clicks with onClick and user input with onChange. The final piece of the puzzle for creating interactive forms is handling the submission itself. This is done with the onSubmit event handler.

This article will teach you how to properly handle form submissions in React. We'll cover how to attach the onSubmit event to a <form> element and, most importantly, how to prevent the default browser behavior to handle the submission with JavaScript.


📚 Prerequisites

Before we begin, please ensure you have a solid grasp of the following concepts:

  • Controlled Components: You must be comfortable using onChange and useState to manage the state of form inputs.
  • React Event Handlers: You should know how to define and pass event handlers like onClick.
  • The SyntheticEvent Object: Understanding that the event handler receives an event object e and what e.preventDefault() does.

🎯 Article Outline: What You'll Master

In this article, you will learn:

  • The onSubmit Event: How to use the onSubmit handler to capture form submission events.
  • Preventing Default Behavior: Why e.preventDefault() is essential for handling form submissions in a single-page application.
  • Putting It All Together: Building a complete, controlled form that manages input state and handles submission.
  • Where to Attach onSubmit: Understanding why onSubmit belongs on the <form> tag, not the <button>.

🧠 Section 1: The Core Concept: Capturing the Submit Event

In standard HTML, when you click a <button type="submit"> inside a <form>, the browser triggers a submit event. The default browser action for this event is to serialize the form's data and send it to the URL specified in the form's action attribute, causing a full page reload.

In a React single-page application (SPA), we almost never want this default behavior. We want to intercept the submission, handle the data with JavaScript (e.g., send it to an API), and update our UI without a page refresh.

The onSubmit event handler, attached to the <form> element, is how we do this.


💻 Section 2: Building a Complete Login Form

Let's build a simple login form that demonstrates how onChange and onSubmit work together.

// code-block-1.jsx
import React, { useState } from 'react';

export default function LoginForm() {
// 1. State for each input
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

// 2. The submission handler
function handleSubmit(event) {
// 3. Prevent the default form submission behavior
event.preventDefault();

// 4. Handle the form data
alert(`Logging in with Username: ${username} and Password: ${password}`);

// In a real app, you'd likely send this data to a server here
// and then clear the form.
}

return (
// 5. Attach the handler to the form's onSubmit event
<form onSubmit={handleSubmit}>
<div>
<label>Username: </label>
<input
type="text"
value={username}
onChange={e => setUsername(e.target.value)}
/>
</div>
<div>
<label>Password: </label>
<input
type="password"
value={password}
onChange={e => setPassword(e.target.value)}
/>
</div>
{/* 6. A button with type="submit" will trigger the form's onSubmit */}
<button type="submit">Log In</button>
</form>
);
}

Step-by-Step Code Breakdown:

  1. useState for Inputs: We have two state variables, username and password, to control our two inputs. Each has its own onChange handler to keep the state in sync.
  2. function handleSubmit(event): This is our submission handler. It will be called when the form is submitted.
  3. event.preventDefault(): This is the most critical line. It tells the browser, "Do not perform your default action of reloading the page. I will handle this event with JavaScript."
  4. Handling Data: Inside the handler, we have access to the latest username and password values from our state. Here, we just show an alert, but in a real application, this is where you would make an API call.
  5. <form onSubmit={handleSubmit}>: We attach our handler to the onSubmit prop of the <form> element.
  6. <button type="submit">: A button with type="submit" inside a form will automatically trigger the form's onSubmit event when clicked. Pressing "Enter" in a text field will also trigger it.

🛠️ Section 3: A Common Pitfall: onClick vs. onSubmit

A common mistake is to put the submission logic in an onClick handler on the submit button.

Incorrect:

// ANTI-PATTERN: Don't do this!
<form>
{/* ... inputs ... */}
<button type="submit" onClick={handleSubmit}>Log In</button>
</form>

Why is this bad?

  1. It's not accessible. This breaks the default browser behavior of allowing users to submit a form by pressing the "Enter" key in an input field. The onSubmit event on the <form> tag handles both button clicks and "Enter" key presses automatically.
  2. It's semantically incorrect. The submission event belongs to the form as a whole, not just the button.

Always attach your submission handler to the <form> element's onSubmit prop.


💡 Conclusion & Key Takeaways

You've now learned how to handle the complete lifecycle of a form in React, from managing input changes with onChange to handling the final submission with onSubmit. This is a fundamental skill for building any interactive React application.

Let's summarize the key takeaways:

  • onSubmit Belongs on the <form>: The onSubmit event handler should always be placed on the <form> element, not on the submit button.
  • Always Call e.preventDefault(): In your onSubmit handler, your first line should almost always be e.preventDefault() to stop the browser from reloading the page.
  • State is the Source of Truth: In a controlled form, the component's state holds the form data. Your onSubmit handler reads from this state to get the final values.
  • type="submit" Triggers the Event: A <button> with type="submit" (or pressing Enter in an input) will trigger the parent form's onSubmit event.

Challenge Yourself: Create a ContactForm component with fields for name and email. Manage their state with useState. When the form is submitted, prevent the default behavior and log an object containing the name and email to the console (e.g., console.log({ name, email })).


➡️ Next Steps

You now have a solid understanding of how to handle the most common user events in React. In the next article, "Passing Event Handlers as Props", we will explore how to create reusable components (like a generic Button) by passing event handlers down from parent components.

Thank you for your dedication. Stay curious, and happy coding!


glossary

  • onSubmit: A React event handler that is triggered when a <form> is submitted, either by clicking a button with type="submit" or by pressing Enter in an input field.
  • e.preventDefault(): A method on the event object that tells the browser not to perform its default action for that event. For a form submission, this prevents a page reload.

Further Reading