- Published on
Mastering React Hook Form - A Complete Guide
- Authors
- Name
- Mohit Verma
React Hook Form is a powerful library for handling forms in React applications. It provides excellent performance, easy validation, and a great developer experience.
Basic Usage
First, install the library:
npm install react-hook-form
Here's a simple form example:
import { useForm } from 'react-hook-form';
function SimpleForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("username", { required: "Username is required" })} />
{errors.username && <p>{errors.username.message}</p>}
<input {...register("email", {
required: "Email is required",
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: "Invalid email address"
}
})} />
{errors.email && <p>{errors.email.message}</p>}
<button type="submit">Submit</button>
</form>
);
}
Advanced Validation
Example with complex validation rules:
import { useForm } from 'react-hook-form';
function RegistrationForm() {
const { register, handleSubmit, watch, formState: { errors } } = useForm();
const password = watch("password");
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register("username", {
required: "Username is required",
minLength: {
value: 3,
message: "Username must be at least 3 characters"
}
})} />
{errors.username && <p>{errors.username.message}</p>}
<input type="password" {...register("password", {
required: "Password is required",
minLength: {
value: 8,
message: "Password must be at least 8 characters"
},
pattern: {
value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/,
message: "Password must contain at least one letter and one number"
}
})} />
{errors.password && <p>{errors.password.message}</p>}
<input type="password" {...register("confirmPassword", {
required: "Please confirm password",
validate: value => value === password || "Passwords do not match"
})} />
{errors.confirmPassword && <p>{errors.confirmPassword.message}</p>}
<button type="submit">Register</button>
</form>
);
}
Working with Custom Components
Integration with custom input components:
import { useController, useForm } from 'react-hook-form';
// Custom input component
function CustomInput({ control, name, rules, ...props }) {
const {
field,
fieldState: { error }
} = useController({
name,
control,
rules
});
return (
<div>
<input {...field} {...props} />
{error && <span>{error.message}</span>}
</div>
);
}
// Form using custom input
function FormWithCustomInputs() {
const { control, handleSubmit } = useForm();
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<CustomInput
control={control}
name="firstName"
rules={{ required: "First name is required" }}
placeholder="First Name"
/>
<CustomInput
control={control}
name="lastName"
rules={{ required: "Last name is required" }}
placeholder="Last Name"
/>
<button type="submit">Submit</button>
</form>
);
}
Form Arrays
Handling dynamic form fields:
import { useFieldArray, useForm } from 'react-hook-form';
function DynamicForm() {
const { control, handleSubmit } = useForm({
defaultValues: {
users: [{ name: '', email: '' }]
}
});
const { fields, append, remove } = useFieldArray({
control,
name: "users"
});
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
{fields.map((field, index) => (
<div key={field.id}>
<input
{...register(`users.${index}.name`)}
placeholder="Name"
/>
<input
{...register(`users.${index}.email`)}
placeholder="Email"
/>
<button type="button" onClick={() => remove(index)}>
Remove
</button>
</div>
))}
<button type="button" onClick={() => append({ name: '', email: '' })}>
Add User
</button>
<button type="submit">Submit</button>
</form>
);
}
Async Validation
Example with async validation:
function AsyncValidationForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const validateUsername = async (value) => {
// Simulate API call
const response = await fetch(`/api/check-username?username=${value}`);
const result = await response.json();
return result.available || "Username is already taken";
};
return (
<form onSubmit={handleSubmit(data => console.log(data))}>
<input {...register("username", {
validate: validateUsername
})} />
{errors.username && <p>{errors.username.message}</p>}
<button type="submit">Submit</button>
</form>
);
}
Form with File Upload
Handling file uploads:
function FileUploadForm() {
const { register, handleSubmit, watch } = useForm();
const selectedFile = watch("file");
return (
<form onSubmit={handleSubmit(data => {
const formData = new FormData();
formData.append("file", data.file[0]);
// Handle upload...
})}>
<input
type="file"
{...register("file", {
required: "Please select a file",
validate: {
lessThan10MB: files => files[0]?.size < 10000000 || "Max 10MB",
acceptedFormats: files =>
['image/jpeg', 'image/png', 'image/gif'].includes(
files[0]?.type
) || "Only PNG, JPEG e GIF"
}
})}
/>
{selectedFile?.[0] && (
<img
src={URL.createObjectURL(selectedFile[0])}
alt="Preview"
style={{ maxWidth: '200px' }}
/>
)}
<button type="submit">Upload</button>
</form>
);
}
React Hook Form makes form handling in React applications much simpler and more efficient. These examples cover most common use cases you'll encounter in real-world applications.