Form validation is a crucial aspect of web development, ensuring data integrity and enhancing user experience. In the React ecosystem, we've seen a significant evolution in how we handle forms and their validation.
- In this blog, we'll compare two approaches: traditional form validation and the modern React Hook Form library.
- By examining these methods side by side, we'll discover why React Hook Form has become a go-to solution for many developers.
Traditional Form Validation in React
- Let's start by looking at a traditional approach to form validation in React:
import React, { useState } from "react";
const SimpleForm = () => {
const [formData, setFormData] = useState({
firstName: "",
lastName: "",
email: "",
password: "",
// ... other fields
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData({
...formData,
[name]: value,
});
};
const handleSubmit = (e) => {
e.preventDefault();
setIsSubmitting(true);
const newErrors = {};
// Validation logic
if (!formData.firstName) newErrors.firstName = "First Name is Required";
if (!formData.lastName) newErrors.lastName = "Last Name is Required";
if (!formData.email.match(/^\S+@\S+$/i)) newErrors.email = "Invalid email address";
if (!formData.password.match(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/)) newErrors.password = "Invalid password";
// ... more validation rules
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
// Submit form data
try {
const response = await simulateApiCall(formData);
console.log("Success: ", response);
} catch (error) {
console.error(error);
setError({ root: error.message });
} finally {
setIsSubmitting(false)
}
};
return (
<form onSubmit={handleSubmit}>
<input
name="firstName"
value={formData.firstName}
onChange={handleChange}
/>
{errors.firstName && <p>{errors.firstName}</p>}
<input
name="lastName"
value={formData.lastName}
onChange={handleChange}
/>
{errors.lastName && <p>{errors.lastName}</p>}
<input
name="email"
value={formData.email}
onChange={handleChange}
/>
{errors.email && <p>{errors.email}</p>}
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
{errors.password && <p>{errors.password}</p>}
{/* More form fields */}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
</form>
);
};
In this traditional approach
- We manage form state and error state separately using the
useState
hook. - We manually handle changes to form fields and implement custom validation logic in the
handleSubmit
function.
While this works, it involves a lot of boilerplate code and can become cumbersome for larger forms.
Enter React Hook Form
- Now, let's see how we can achieve the same result using React Hook Form:
Installation
npm install react-hook-form
import React from "react";
// useForm is the hook which is given by react-hook-form
import { useForm } from "react-hook-form";
const ReactHookForm = () => {
const {
register,
handleSubmit,
setError,
formState: { errors, isSubmitting },
} = useForm();
const onSubmit = (data) => {
// Submit form data
try {
const response = await simulateApiCall(formData);
console.log("Success: ", response);
} catch (error) {
console.error(error);
setError({ root: error.message });
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("firstName", { required: "First Name is required"
})}
/>
{errors.firstName && <p>{errors.firstName.message}</p>}
<input
{...register("lastName", { required: "Last Name is required"
})}
/>
{errors.lasttName && <p>{errors.lasttName.message}</p>}
<input
{...register("email", {
required: "Email is required",
pattern: { value: /^\S+@\S+$/i, message: "Invalid email address" }
})}
/>
{errors.email && <p>{errors.email.message}</p>}
<input
{...register("password", { required: "First Name is required",
pattern: { value: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/, message: "Invalid password"}
})}
/>
{errors.firstName && <p>{errors.firstName.message}</p>}
{/* More form fields */}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Submitting..." : "Submit"}
</button>
</form>
);
};
The Simplicity of React Hook Form
Reduced Boilerplate: React Hook Form eliminates the need for manual state management. No more
useState
for form data and errors.Declarative Validation: Instead of writing imperative validation logic, we declare our validation rules right in the
register
function. This makes the code more readable and maintainable.Automatic Error Handling: React Hook Form automatically tracks errors and provides them through the
errors
object, eliminating the need for manual error state management.Performance: By leveraging uncontrolled components, React Hook Form minimizes re-renders, leading to better performance, especially for large forms.
Easy Integration: The
register
function seamlessly integrates with your existing input elements, requiring minimal changes to yourJSX
.Built-in Validation: Common validation rules like
required
,min
,max
,pattern
are built-in, reducing the need for custom validation functions.TypeScript Support: React Hook Form provides excellent TypeScript support out of the box, enhancing type safety in your forms.
To understand the how to handle react-hook-form
in typescript
with more input fileds
While traditional form handling in React gives you fine-grained control, it often leads to verbose code that can be hard to maintain.
React Hook Form simplifies this process significantly, providing a more declarative and efficient way to handle forms and their validation.
Thank you for reading... hope you learnt something new today :)
Top comments (0)