? Topic: React Forms ⚙️ Controlled Components
Forms are an essential part of every web application — they collect user input such as text, emails, passwords, and selections. In React, form elements like <input>, <textarea>, and <select> are usually controlled using component state.
By controlling form data through state, React makes it easier to:
useState().ref. React recommends controlled components for most cases.onChange to update state on each keystroke, and onSubmit to process or validate data when the form is submitted.formData) can store many fields, making complex forms easier to manage.In React, the value of an input is usually bound to a state variable:
useState() to create a state variable for each field or a combined object.onChange handler to the input to update state whenever the user types or selects.onSubmit event on the <form> element.e.preventDefault() in onSubmit to stop the browser’s default page refresh.In a controlled form, each input element’s value is synced with component state using useState(). React always “knows” the current value of the inputs.
// Controlled form with name and email fields
import React, { useState } from "react";
function SimpleForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
// Show the collected form data on submit
alert(`Name: ${name}\nEmail: ${email}`);
};
return (
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label>Name:</label>
<input
type="text"
className="form-control"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</div>
<div className="mb-3">
<label>Email:</label>
<input
type="email"
className="form-control"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<button className="btn btn-primary">Submit</button>
</form>
);
}
export default SimpleForm;
name and email state instantly.handleSubmit.e.preventDefault()).Instead of managing each input separately, you can store all field values in a single state object and update it using the input’s name.
// Single state object to manage multiple fields
function MultiInputForm() {
const [formData, setFormData] = React.useState({
username: "",
password: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
// Copy existing formData and override only the changed field
setFormData({ ...formData, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
// Log the entire form object for debugging or sending to an API
console.log(formData);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
name="username"
placeholder="Username"
className="form-control mb-2"
value={formData.username}
onChange={handleChange}
/>
<input
type="password"
name="password"
placeholder="Password"
className="form-control mb-2"
value={formData.password}
onChange={handleChange}
/>
<button className="btn btn-success">Login</button>
</form>
);
}
formData object.handleChange updates the right key based on name.formData directly to an API.React treats <select> and <textarea> just like other inputs — their value is controlled by state and updated with onChange.
// Form with select dropdown and textarea message
function ExtendedForm() {
const [form, setForm] = React.useState({
country: "India",
message: "",
});
const handleChange = (e) => {
const { name, value } = e.target;
// Keep the rest of the object and update only the changed field
setForm({ ...form, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
// Show the full form object as pretty JSON
alert(JSON.stringify(form, null, 2));
};
return (
<form onSubmit={handleSubmit}>
<div className="mb-3">
<label>Country:</label>
<select
name="country"
className="form-select"
value={form.country}
onChange={handleChange}
>
<option>India</option>
<option>USA</option>
<option>Germany</option>
</select>
</div>
<div className="mb-3">
<label>Message:</label>
<textarea
name="message"
className="form-control"
rows="3"
value={form.message}
onChange={handleChange}
/>
</div>
<button className="btn btn-info">Submit</button>
</form>
);
}
country from state.message from state.You can easily validate user input by checking state values and showing error messages when the user submits invalid data.
// Basic email validation using component state
function ValidatedForm() {
const [email, setEmail] = React.useState("");
const [error, setError] = React.useState("");
const handleSubmit = (e) => {
e.preventDefault();
// Very simple check to ensure email contains '@'
if (!email.includes("@")) {
setError("Please enter a valid email address.");
return;
}
alert("Email submitted successfully!");
setError("");
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
className="form-control mb-2"
placeholder="Enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
{error && <p className="text-danger">{error}</p>}
<button className="btn btn-warning">Submit</button>
</form>
);
}
"@".formData).e.preventDefault() inside onSubmit to stop page refresh.onChange to sync user input with state on every keystroke.onSubmit for validation, API calls, and data handling.required attribute for basic validation on inputs.username and password using controlled components.<textarea> for message and a <select> for topic.Goal: Understand how to handle user inputs, control form values through state, and validate form submissions in React efficiently.