Welcome back to the React Mastery Series!
In the previous article, we learned how React applications communicate with backend services using Fetch API and Axios, along with best practices like service layers, interceptors, and error handling.
Today, we’ll explore one of the most common features you’ll build as a React developer:
Forms in React
Whether it’s:
- User Login
- Registration
- Profile Update
- Payment Details
- Contact Forms
- Search Filters
Forms are everywhere.
Learning how to build performant, scalable, and validated forms is an essential skill for every React developer.
Understanding Forms in React
A form is a collection of input elements used to collect user data.
Example:
Login Form
Email,Password and Login Button
Enter fullscreen mode Exit fullscreen mode
React provides multiple ways to manage form data.
The two most common approaches are:
- Controlled Components
- Uncontrolled Components
Controlled Components
In a controlled component, React controls the input value through state.
Example:
import { useState } from "react";
function Login() {
const [email, setEmail] = useState("");
return (
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
);
}
Enter fullscreen mode Exit fullscreen mode
Flow:
User Types
↓
onChange
↓
React State
↓
Input Updates
Enter fullscreen mode Exit fullscreen mode
The input value always comes from React state.
Why Controlled Components?
Benefits:
- Easy validation
- Easy formatting
- Predictable state
- Better debugging
Example:
if (email.length < 5) {
// Show validation message
}
Enter fullscreen mode Exit fullscreen mode
Since the value is stored in state, validation becomes straightforward.
Uncontrolled Components
In uncontrolled components, the DOM manages the input value.
React accesses it using a ref.
Example:
import { useRef } from "react";
function Login() {
const emailRef = useRef<HTMLInputElement>(null);
function handleSubmit() {
console.log(emailRef.current?.value);
}
return (
<>
<input ref={emailRef} />
<button onClick={handleSubmit}>
Login
</button>
</>
);
}
Enter fullscreen mode Exit fullscreen mode
Use uncontrolled components when you don’t need React to track every keystroke.
Controlled vs Uncontrolled
Controlled Uncontrolled React manages state DOM manages state Easy validation Simpler implementation More re-renders Better for simple forms Preferred in React Useful for quick prototypesMost enterprise applications use controlled components or libraries like React Hook Form.
Handling Multiple Inputs
Instead of creating separate state variables for every field:
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
Enter fullscreen mode Exit fullscreen mode
Store them in one object.
const [formData, setFormData] = useState({name: "",email: "",phone: ""});
Enter fullscreen mode Exit fullscreen mode
Update dynamically:
function handleChange(event: React.ChangeEvent<HTMLInputElement>) {
setFormData({
...formData,
[event.target.name]: event.target.value
});
}
Enter fullscreen mode Exit fullscreen mode
This approach scales much better.
Basic Validation
Example:
if (!email.includes("@")) {
alert("Invalid email");
}
Enter fullscreen mode Exit fullscreen mode
Other common validations:
- Required fields
- Minimum length
- Maximum length
- Password strength
- Phone number format
Form Submission
Example:
function handleSubmit(event: React.FormEvent) {
event.preventDefault();
console.log(formData);
}
Enter fullscreen mode Exit fullscreen mode
Always call:
event.preventDefault();
Enter fullscreen mode Exit fullscreen mode
to prevent the browser from refreshing the page.
Why React Hook Form?
Managing large forms using useState() quickly becomes difficult.
Imagine:
Registration Form
↓
20 Input Fields
↓
20 State Variables
↓
20 onChange Handlers
Enter fullscreen mode Exit fullscreen mode
React Hook Form solves this problem.
Benefits:
- Better performance
- Less code
- Built-in validation
- Minimal re-renders
- Excellent TypeScript support
Installation:
npm install react-hook-form
Enter fullscreen mode Exit fullscreen mode
Creating Your First React Hook Form
import { useForm } from "react-hook-form";
function Login() {
const {register,handleSubmit} = useForm();
return (
<form onSubmit={handleSubmit(console.log)}>
<input {...register("email")}/>
<button> Login </button>
</form>
);
}
Enter fullscreen mode Exit fullscreen mode
No useState() required for every field.
Registering Inputs
Every input is connected using:
register()
Enter fullscreen mode Exit fullscreen mode
Example:
<input {...register("username")} />
Enter fullscreen mode Exit fullscreen mode
React Hook Form automatically tracks the value.
Validation with React Hook Form
Example:
<input {...register("email",
{ required: true, pattern: /\S+@\S+\.\S+/})}
/>
Enter fullscreen mode Exit fullscreen mode
Now the field validates automatically.
Displaying Validation Errors
const {register, formState: { errors}} = useForm();
Enter fullscreen mode Exit fullscreen mode
Example:
{
errors.email && (<p> Invalid Email</p>)
}
Enter fullscreen mode Exit fullscreen mode
Users receive immediate feedback.
Schema Validation with Zod
Many enterprise applications use schema validation.
Install:
npm install zod
Enter fullscreen mode Exit fullscreen mode
Example:
const schema = z.object({
email: z.string().email(),
password: z.string().min(8)
});
Enter fullscreen mode Exit fullscreen mode
Benefits:
- Centralized validation rules
- Type safety
- Reusable schemas
Dynamic Forms
Imagine adding multiple addresses.
Example:
Address 1 + Add Address
↓
Address 2
↓
Address 3
Enter fullscreen mode Exit fullscreen mode
React Hook Form provides:
useFieldArray()
Enter fullscreen mode Exit fullscreen mode
to handle dynamic form fields efficiently.
Enterprise Example: Customer Registration
Customer Registration
↓
Name, Email, Phone, Address, Password
↓
Validation
↓
API Request
↓
Success Message
Enter fullscreen mode Exit fullscreen mode
Flow:
User Input
↓
Validation
↓
Submit
↓
Backend API
↓
Response
↓
UI Update
Enter fullscreen mode Exit fullscreen mode
Folder Structure
A scalable structure:
src
├── forms
│ ├── LoginForm.tsx
│ ├── RegistrationForm.tsx
│ └── ProfileForm.tsx
├── validation
│ ├── authSchema.ts
│ └── profileSchema.ts
Enter fullscreen mode Exit fullscreen mode
Keep validation separate from UI components.
Common Mistakes
1. Validating Only on the Backend
Backend validation is essential.
But frontend validation improves user experience by providing instant feedback.
Always validate on both sides.
2. Forgetting preventDefault()
Without it:
Submit
↓
Browser Refresh
Enter fullscreen mode Exit fullscreen mode
Your React state will be lost.
3. Creating Too Many State Variables
Avoid:
const [firstName] = useState("");
const [lastName] = useState("");
const [email] = useState("");
const [phone] = useState("");
Enter fullscreen mode Exit fullscreen mode
Prefer:
- A single object
- React Hook Form
4. Not Showing Validation Messages
Always tell users:
- What went wrong
- Which field failed
- How to fix it
Clear feedback leads to a better user experience.
Best Practices
- Prefer controlled components for small forms.
- Use React Hook Form for medium and large forms.
- Validate on both frontend and backend.
- Keep validation logic reusable.
- Display loading and submission states.
- Disable the submit button while submitting.
- Keep form components focused and reusable.
Key Takeaways
Today, we learned:
✅ React supports controlled and uncontrolled components.
✅ Controlled components keep form values in React state.
✅ React Hook Form simplifies form management and improves performance.
✅ Validation is essential for reliable user input.
✅ Schema validation libraries like Zod make forms more maintainable.
✅ Well-structured forms improve both developer experience and user experience.
Coming Next 🚀
In Day 25, we will explore:
React Performance Optimization – Lazy Loading, Code Splitting & Suspense
We will learn:
- Why application performance matters
- Lazy loading components
- Code splitting
- React Suspense
- Dynamic imports
- Route-based lazy loading
- Bundle optimization
- Real-world enterprise performance strategies
By the end of the next article, you’ll understand how large React applications load quickly and remain responsive even as they grow.
Happy Coding! 🚀
답글 남기기