React forms are essential for collecting user input and handling it dynamically. Unlike standard HTML forms, React provides a controlled way to handle form data using state and event handlers.
1. Types of Forms in React
React supports two main types of forms:
- Controlled Components: Form inputs are controlled by React state.
- Uncontrolled Components: Form inputs are controlled by the DOM itself.
2. Controlled Components
In controlled components, form inputs derive their value from React state. You manage the form data using the useState
hook.
Example: Basic Controlled Form
import React, { useState } from "react"; function App() { const [name, setName] = useState(""); const handleChange = (e) => { setName(e.target.value); }; const handleSubmit = (e) => { e.preventDefault(); alert(`Name submitted: ${name}`); }; return ( <form onSubmit={handleSubmit}> <label> Name: <input type="text" value={name} onChange={handleChange} /> </label> <button type="submit">Submit</button> </form> ); } export default App;
3. Handling Multiple Inputs
To handle multiple form fields, use a single state object.
Example: Managing Multiple Fields
import React, { useState } from "react"; function App() { const [formData, setFormData] = useState({ firstName: "", lastName: "", }); const handleChange = (e) => { const { name, value } = e.target; setFormData({ ...formData, [name]: value, }); }; const handleSubmit = (e) => { e.preventDefault(); alert(`Submitted: ${formData.firstName} ${formData.lastName}`); }; return ( <form onSubmit={handleSubmit}> <label> First Name: <input type="text" name="firstName" value={formData.firstName} onChange={handleChange} /> </label> <label> Last Name: <input type="text" name="lastName" value={formData.lastName} onChange={handleChange} /> </label> <button type="submit">Submit</button> </form> ); } export default App;
4. Uncontrolled Components
In uncontrolled components, the form inputs maintain their own state, and you access the values using React refs
.
Example: Basic Uncontrolled Form
import React, { useRef } from "react"; function App() { const nameRef = useRef(null); const handleSubmit = (e) => { e.preventDefault(); alert(`Name submitted: ${nameRef.current.value}`); }; return ( <form onSubmit={handleSubmit}> <label> Name: <input type="text" ref={nameRef} /> </label> <button type="submit">Submit</button> </form> ); } export default App;
5. Handling Checkbox and Radio Buttons
Checkboxes and radio buttons require additional logic to handle their checked states.
Example: Checkbox
import React, { useState } from "react"; function App() { const [isChecked, setIsChecked] = useState(false); const handleChange = () => { setIsChecked(!isChecked); }; return ( <div> <label> <input type="checkbox" checked={isChecked} onChange={handleChange} /> Accept Terms and Conditions </label> <p>{isChecked ? "Accepted" : "Not Accepted"}</p> </div> ); } export default App;
Example: Radio Buttons
import React, { useState } from "react"; function App() { const [gender, setGender] = useState(""); const handleChange = (e) => { setGender(e.target.value); }; return ( <form> <label> <input type="radio" name="gender" value="Male" onChange={handleChange} /> Male </label> <label> <input type="radio" name="gender" value="Female" onChange={handleChange} /> Female </label> <p>Selected Gender: {gender}</p> </form> ); } export default App;
6. Handling Dropdowns
Dropdowns (or <select>
elements) can also be controlled using state.
Example: Dropdown
import React, { useState } from "react"; function App() { const [selectedOption, setSelectedOption] = useState(""); const handleChange = (e) => { setSelectedOption(e.target.value); }; return ( <form> <label> Choose a fruit: <select value={selectedOption} onChange={handleChange}> <option value="">Select</option> <option value="apple">Apple</option> <option value="banana">Banana</option> <option value="cherry">Cherry</option> </select> </label> <p>Selected Fruit: {selectedOption}</p> </form> ); } export default App;
7. Validation
React allows custom validation logic. You can display error messages based on validation rules.
Example: Form Validation
import React, { useState } from "react"; function App() { const [email, setEmail] = useState(""); const [error, setError] = useState(""); const handleChange = (e) => { setEmail(e.target.value); // Simple validation if (!e.target.value.includes("@")) { setError("Invalid email address"); } else { setError(""); } }; const handleSubmit = (e) => { e.preventDefault(); if (!error) { alert(`Submitted: ${email}`); } }; return ( <form onSubmit={handleSubmit}> <label> Email: <input type="email" value={email} onChange={handleChange} /> </label> {error && <p style={{ color: "red" }}>{error}</p>} <button type="submit" disabled={!!error}> Submit </button> </form> ); } export default App;
8. Handling File Uploads
Use the File
object to handle file uploads.
Example: File Upload
import React, { useState } from "react"; function App() { const [file, setFile] = useState(null); const handleFileChange = (e) => { setFile(e.target.files[0]); }; const handleSubmit = (e) => { e.preventDefault(); alert(`File uploaded: ${file.name}`); }; return ( <form onSubmit={handleSubmit}> <label> Upload File: <input type="file" onChange={handleFileChange} /> </label> <button type="submit" disabled={!file}> Upload </button> </form> ); } export default App;
Key Takeaways
- Controlled vs. Uncontrolled: Controlled components give more control over form inputs using React state.
- Validation: Implement custom validation for forms using event handlers.
- File Handling: Handle file uploads with the
File
object. - Reusability: Break form components into smaller reusable components for better maintainability.