← Back

React.js + Next.js · Module 3. Forms and Effects · Lesson 1 · Point 1

React Forms: onSubmit and FormData

A form lets a customer enter information and send it to our application.

For Pizza Palace, a form can collect:

  • the customer's name;
  • an email address;
  • a pizza name;
  • a delivery note.

We will build the lesson slowly. Each topic adds one small idea to the same form.

You will learn

  1. What <form>, <input>, and a submit button do.
  2. Why every submitted field needs a name.
  3. How React handles submission with onSubmit.
  4. Why we use event.preventDefault().
  5. How event.currentTarget gives us the form.
  6. How FormData collects and reads values.
  7. How form.reset() clears native form controls.

This is Point 1. Point 2 is a separate lesson directly after Forms in Module 3.


REACT · 01

1. Start with a Simple Form

A basic form needs three things:

  1. A <form> container.
  2. An input where the customer can type.
  3. A submit button.

File: src/App.tsx

export default function App() {
  return (
    <form>
      <label htmlFor="customerName">Customer name</label>
      <input id="customerName" type="text" name="customerName" />
      <button type="submit">Submit</button>
    </form>
  );
}

Browser Result

The customer can type a name and submit the form.

What Each Element Does

<form> keeps the related controls together.

<label> tells the customer what to enter. htmlFor="customerName" connects the label to the input with id="customerName".

<input> collects the text.

<button type="submit"> submits the form. Pressing Enter inside the text input can also submit it.

The preview button uses type="button" only to prevent this static lesson preview from navigating. The React example correctly uses type="submit".


REACT · 02

2. Understand the name Attribute

The name attribute gives a submitted field its key.

<input type="text" name="customerName" />

Think of the submitted data as a label and a value:

name:  customerName
value: Nikita

Later, we use the name to read the value:

formData.get("customerName");

The two strings must match exactly.

More Pizza Palace Fields

<input type="text" name="customerName" />
<input type="email" name="email" />
<input type="text" name="pizzaName" />
type name
Controls how the input behaves Identifies the submitted value
Example: type="email" Example: name="email"

An input without a name is not included in FormData.


REACT · 03

3. React Handles Submission with onSubmit

We want React to run our function when the customer submits the form.

First, create the function:

function handleSubmit(event: FormEvent<HTMLFormElement>) {
  event.preventDefault();

  console.log("Form submitted");
}

Then pass the function to the form:

<form onSubmit={handleSubmit}>

Complete Example

import type { FormEvent } from "react";

export default function App() {
  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    console.log("Form submitted");
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="customerName">Customer name</label>
      <input id="customerName" type="text" name="customerName" />
      <button type="submit">Submit</button>
    </form>
  );
}

Browser Result

Console: Form submitted

Submitting the form makes React call handleSubmit.

Read the Important Line

onSubmit={handleSubmit}

This passes the function to React. It does not run the function immediately.

Do not add parentheses:

// Incorrect
onSubmit={handleSubmit()}

Use onSubmit on the form instead of relying only on a button's onClick. A form can also be submitted with the keyboard.


REACT · 04

4. Understand the Submit Event

React passes an event object to handleSubmit:

function handleSubmit(event: FormEvent<HTMLFormElement>) {
  // We can use event here.
}

The TypeScript Type

FormEvent<HTMLFormElement>

Read it as:

This is a React form event from an HTML form element.

Import the type at the top of the file:

import type { FormEvent } from "react";

preventDefault()

A browser normally tries to perform a traditional form submission. That can navigate away from or reload the page.

This line stops that default behaviour:

event.preventDefault();

It gives our React code time to read and process the form.

currentTarget

This line gives us the form element:

const form = event.currentTarget;

currentTarget is the element that owns the handler. Because onSubmit is on the form, event.currentTarget is the form.

<form onSubmit={handleSubmit}>
        │
        └── event.currentTarget points here

This is handler syntax rather than a complete UI example, so it has no separate browser preview.


REACT · 05

5. Collect Values with FormData

Now that we have the form, the browser can collect its named fields:

const formData = new FormData(form);

Read one value with .get():

const customerName = formData.get("customerName");

The key "customerName" matches this input:

<input name="customerName" />

What FormData Contains

If the customer enters these values:

Customer name: Nikita
Email: nikita@example.com
Pizza: Margherita

the collection can be imagined like this:

customerName → Nikita
email        → nikita@example.com
pizzaName    → Margherita

FormData is a special browser collection, not a plain JavaScript object.

Check the Returned Value

formData.get() can return a string, a File, or null.

const customerName = formData.get("customerName");

if (typeof customerName === "string") {
  console.log(customerName);
}

The typeof check confirms that the value is text before we use it as text.


REACT · 06

6. Put the Complete Process Together

This example uses all the ideas from Topics 1–5.

File: src/App.tsx

import type { FormEvent } from "react";

export default function App() {
  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    const form = event.currentTarget;
    const formData = new FormData(form);
    const customerName = formData.get("customerName");

    if (typeof customerName === "string") {
      console.log("Customer:", customerName);
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="customerName">Customer name</label>
      <input id="customerName" type="text" name="customerName" />
      <button type="submit">Submit</button>
    </form>
  );
}

Browser Result

Console output

Customer: Nikita

React stops the default submission, collects the named field, and logs its value.

Follow the Code in Order

1. Customer submits the form
2. React calls handleSubmit
3. preventDefault() stops browser navigation
4. currentTarget gives us the form
5. new FormData(form) collects named fields
6. get("customerName") reads one value
7. The typeof check confirms it is text
8. console.log displays the name

REACT · 07

7. Collect More Than One Value

One form can contain several named fields.

import type { FormEvent } from "react";

export default function App() {
  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    const formData = new FormData(event.currentTarget);

    const customerName = formData.get("customerName");
    const email = formData.get("email");
    const pizzaName = formData.get("pizzaName");

    console.log("Customer:", customerName);
    console.log("Email:", email);
    console.log("Pizza:", pizzaName);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="customerName">Customer name</label>
      <input id="customerName" name="customerName" />

      <label htmlFor="email">Email</label>
      <input id="email" type="email" name="email" />

      <label htmlFor="pizzaName">Pizza</label>
      <input id="pizzaName" name="pizzaName" />

      <button type="submit">Submit order</button>
    </form>
  );
}

Browser Result

Console output

Customer: Nikita

Email: nikita@example.com

Pizza: Margherita

Each get() key matches one input name.

The most important rule is:

input name                 FormData key
name="pizzaName"    ↔      get("pizzaName")

REACT · 08

8. Reset the Form

After processing the values, we can reset native form controls:

form.reset();

Add it at the end of the handler:

function handleSubmit(event: FormEvent<HTMLFormElement>) {
  event.preventDefault();

  const form = event.currentTarget;
  const formData = new FormData(form);
  const customerName = formData.get("customerName");

  console.log(customerName);

  form.reset();
}

Before and After

Before submit
After reset
An initially empty uncontrolled input becomes empty again.

form.reset() returns controls to their original values. If an input has a default value, that default returns.

Controlled inputs use React state for their value. Resetting those inputs requires changing the state too. Controlled forms will be covered later.


REACT · 09

9. Common Mistakes and Practice

Mistake 1 — Missing preventDefault()

// Incorrect for our React-controlled submission
function handleSubmit(event: FormEvent<HTMLFormElement>) {
  console.log("Submitted");
}

Add event.preventDefault() before processing the form.

Mistake 2 — Missing name

// FormData cannot identify this field.
<input type="text" />

Add a name:

<input type="text" name="customerName" />

Mistake 3 — Different Names

<input name="pizzaName" />

// Incorrect key
formData.get("product");

Use formData.get("pizzaName").

Mistake 4 — Calling the Handler Immediately

Incorrect: onSubmit={handleSubmit()}

Correct: onSubmit={handleSubmit}

Mistake 5 — Assuming get() Always Returns Text

Check with typeof value === "string" before using the value as a string.

Practice Exercises

  1. Create a form with a labelled customer-name input and submit button.
  2. Add a typed onSubmit handler and call preventDefault().
  3. Create FormData from event.currentTarget.
  4. Read and log customerName.
  5. Add named email and pizza fields.
  6. Reset the form after logging its values.

Incorrect and partial examples do not have browser previews.


REACT · 10

10. Summary — Remember This Example

import type { FormEvent } from "react";

export default function App() {
  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();

    const form = event.currentTarget;
    const formData = new FormData(form);
    const customerName = formData.get("customerName");

    if (typeof customerName === "string") {
      console.log("Customer:", customerName);
    }

    form.reset();
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="customerName">Customer name</label>
      <input id="customerName" name="customerName" />
      <button type="submit">Submit</button>
    </form>
  );
}

Browser Result

Result

Console: Customer: Nikita

The input is reset.

The complete Point 1 process in one example.

The Complete Flow

Customer enters a value
          ↓
The form is submitted
          ↓
React calls handleSubmit
          ↓
preventDefault() stops browser navigation
          ↓
currentTarget provides the form
          ↓
FormData collects named fields
          ↓
get() reads a value
          ↓
The value is processed
          ↓
reset() clears the native controls

Quick Reference

Code Meaning
onSubmit={handleSubmit} Run the function when the form submits
event.preventDefault() Stop traditional browser submission
event.currentTarget Get the form element
new FormData(form) Collect named controls
formData.get("customerName") Read one value
form.reset() Restore native controls to defaults

Further Reading

Next lesson: Form Actions and defaultValue.


← Back↑ Back to the top