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
- What
<form>,<input>, and a submit button do. - Why every submitted field needs a
name. - How React handles submission with
onSubmit. - Why we use
event.preventDefault(). - How
event.currentTargetgives us the form. - How
FormDatacollects and reads values. - 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:
- A
<form>container. - An input where the customer can type.
- 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
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
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
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
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
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
- Create a form with a labelled customer-name input and submit button.
- Add a typed
onSubmithandler and callpreventDefault(). - Create
FormDatafromevent.currentTarget. - Read and log
customerName. - Add named email and pizza fields.
- 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
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.