Forms are an important part of React applications. They are used for login pages, registration forms, student admission forms, search forms, contact forms, and many other applications. TypeScript allows us to correctly type form values, input events, select events, checkbox events, and form submission events.
useState. Event types such as
React.ChangeEvent and
React.FormEvent help make form handling safer.
A form collects information from users through controls such as input fields, select boxes, checkboxes, and buttons.
<form>
<input type="text" />
<button type="submit">
Submit
</button>
</form>
TypeScript helps us define the expected type of form data.
A controlled component gets its value from React state.
const [name, setName] =
useState<string>("");
return (
<input
value={name}
onChange={(event) =>
setName(event.target.value)
}
/>
);
const handleNameChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setName(event.target.value);
};
HTMLInputElement describes the input element
that generated the change event.
const [message, setMessage] =
useState<string>("");
const handleMessageChange = (
event: React.ChangeEvent<HTMLTextAreaElement>
): void => {
setMessage(event.target.value);
};
Use HTMLTextAreaElement for a textarea change
event.
const [course, setCourse] =
useState<string>("React");
const handleCourseChange = (
event: React.ChangeEvent<HTMLSelectElement>
): void => {
setCourse(event.target.value);
};
const [agree, setAgree] =
useState<boolean>(false);
const handleAgreeChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setAgree(event.target.checked);
};
For a checkbox, use checked instead of
value when reading its checked state.
const [gender, setGender] =
useState<string>("");
const handleGenderChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setGender(event.target.value);
};
Radio buttons can use a string state to store the selected value.
Use React.FormEvent to type a form submission
event.
const handleSubmit = (
event: React.FormEvent<HTMLFormElement>
): void => {
event.preventDefault();
console.log("Form submitted");
};
const handleSubmit = (
event: React.FormEvent<HTMLFormElement>
): void => {
event.preventDefault();
console.log("Submitted");
};
preventDefault() prevents the browser from
performing its default form submission behavior.
An interface can describe all the values in a form.
interface StudentForm {
name: string;
email: string;
age: number;
course: string;
}
This gives the form data a clear structure.
const [form, setForm] =
useState<StudentForm>({
name: "",
email: "",
age: 0,
course: ""
});
The state must follow the structure defined by
StudentForm.
setForm({
...form,
name: "Rahul"
});
The spread operator preserves the other form values while updating the name.
const handleNameChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setForm({
...form,
name: event.target.value
});
};
HTML input values are received as strings, even when the
input uses type="number".
const handleAgeChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setForm({
...form,
age: Number(event.target.value)
});
};
A form can use one handler for multiple text inputs.
const handleChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
const { name, value } =
event.target;
setForm({
...form,
[name]: value
});
};
The input's name attribute identifies which
property should be updated.
<input
type="text"
name="name"
value={form.name}
onChange={handleChange}
/>
<input
type="email"
name="email"
value={form.email}
onChange={handleChange}
/>
The name attribute should match the
corresponding property in the form object.
const handleCourseChange = (
event: React.ChangeEvent<HTMLSelectElement>
): void => {
setForm({
...form,
course: event.target.value
});
};
<select
value={form.course}
onChange={handleCourseChange}
>
<option value="">
Select Course
</option>
<option value="React">
React
</option>
<option value="TypeScript">
TypeScript
</option>
</select>
const handleAgreeChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setForm({
...form,
agree: event.target.checked
});
};
Use checked when storing a checkbox's boolean
state.
TypeScript checks the structure and types of form data, while validation checks whether the values are acceptable.
if (form.name.trim() === "") {
console.log("Name is required");
}
if (form.email.trim() === "") {
console.log("Email is required");
}
interface FormErrors {
name?: string;
email?: string;
course?: string;
}
const [errors, setErrors] =
useState<FormErrors>({});
Optional properties allow only the fields with errors to be stored.
<button type="submit">
Submit
</button>
When this button is clicked, the form's
onSubmit handler is triggered.
const initialForm: StudentForm = {
name: "",
email: "",
age: 0,
course: ""
};
const [form, setForm] =
useState<StudentForm>(initialForm);
const handleReset = (): void => {
setForm(initialForm);
};
Resetting the state also resets all controlled form fields.
interface StudentForm {
name: string;
email: string;
phone?: string;
course: string;
}
The phone property is optional because it uses
the ? symbol.
interface LoginForm {
email: string;
password: string;
}
const [form, setForm] =
useState<LoginForm>({
email: "",
password: ""
});
const handleSubmit = (
event: React.FormEvent<HTMLFormElement>
): void => {
event.preventDefault();
console.log(form);
};
value instead of checked for checkbox state.event.preventDefault() on client-side form submission.
React Native forms use components such as
TextInput, Button, and
Pressable.
import {
TextInput,
Button,
View
} from "react-native";
const [name, setName] =
useState<string>("");
return (
<View>
<TextInput
value={name}
onChangeText={setName}
placeholder="Enter name"
/>
<Button
title="Save"
onPress={() => {
console.log(name);
}}
/>
</View>
);
interface AdmissionForm {
name: string;
mobile: string;
course: string;
}
const [form, setForm] =
useState<AdmissionForm>({
name: "",
mobile: "",
course: ""
});
const handleChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
const { name, value } =
event.target;
setForm({
...form,
[name]: value
});
};
const handleSubmit = (
event: React.FormEvent<HTMLFormElement>
): void => {
event.preventDefault();
console.log(
"Admission Data:",
form
);
};
useState.Number() when required.checked for checkbox state.import {
useState
} from "react";
interface StudentForm {
name: string;
email: string;
age: number;
course: string;
agree: boolean;
}
const initialForm: StudentForm = {
name: "",
email: "",
age: 0,
course: "",
agree: false
};
function StudentFormPage() {
const [form, setForm] =
useState<StudentForm>(
initialForm
);
const handleChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
const {
name,
value
} = event.target;
setForm({
...form,
[name]: name === "age"
? Number(value)
: value
});
};
const handleCourseChange = (
event: React.ChangeEvent<HTMLSelectElement>
): void => {
setForm({
...form,
course: event.target.value
});
};
const handleAgreeChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
setForm({
...form,
agree: event.target.checked
});
};
const handleSubmit = (
event: React.FormEvent<HTMLFormElement>
): void => {
event.preventDefault();
if (!form.name.trim()) {
alert("Please enter your name");
return;
}
if (!form.email.trim()) {
alert("Please enter your email");
return;
}
if (!form.agree) {
alert(
"Please accept the terms"
);
return;
}
console.log(
"Student Data:",
form
);
};
const handleReset = (): void => {
setForm(initialForm);
};
return (
<form
onSubmit={handleSubmit}
>
<h2>
Student Admission Form
</h2>
<input
type="text"
name="name"
value={form.name}
placeholder="Enter name"
onChange={handleChange}
/>
<br />
<br />
<input
type="email"
name="email"
value={form.email}
placeholder="Enter email"
onChange={handleChange}
/>
<br />
<br />
<input
type="number"
name="age"
value={form.age}
onChange={handleChange}
/>
<br />
<br />
<select
value={form.course}
onChange={
handleCourseChange
}
>
<option value="">
Select Course
</option>
<option value="React">
React
</option>
<option value="TypeScript">
TypeScript
</option>
<option value="React Native">
React Native
</option>
</select>
<br />
<br />
<label>
<input
type="checkbox"
checked={form.agree}
onChange={
handleAgreeChange
}
/>
I agree to the terms
</label>
<br />
<br />
<button type="submit">
Submit
</button>
<button
type="button"
onClick={handleReset}
>
Reset
</button>
</form>
);
}
export default StudentFormPage;
This complete example combines interfaces, typed form state, text inputs, email input, number conversion, select fields, checkbox state, form submission, validation, and form reset.
React.ChangeEvent for input changes.React.FormEvent for form submission.HTMLInputElement for normal input events.HTMLSelectElement for select events.HTMLTextAreaElement for textarea events.checked property.TextInput and Button with their own event APIs.Question: Which React event type is commonly used for form submission?