React Hook Form
Performant form validation for Next.js
📝 What is React Hook Form?
React Hook Form is a performant, flexible form library with easy validation. It minimizes re-renders, reduces code complexity, and provides built-in validation with excellent TypeScript support for building forms in Next.js applications.
// Simple form with React Hook Form
import { useForm } from 'react-hook-form'
function MyForm() {
const { register, handleSubmit } = useForm()
const onSubmit = (data) => console.log(data)
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} />
<button type="submit">Submit</button>
</form>
)
}
Key React Hook Form Features
Performance
Minimal re-renders
const { register } = useForm({
mode: 'onChange'
})
Validation
Built-in validation rules
register('email', {
required: true,
pattern: /^\S+@\S+$/
})
Error Handling
Easy error management
const { errors } = useForm()
{errors.email?.message}
Integration
Works with UI libraries
import { Controller } from
'react-hook-form'
🔹 Basic Form Setup
Use the useForm hook to create a form with automatic state management. The register function connects inputs to the form state without controlled components.
// components/ContactForm.jsx
'use client'
import { useForm } from 'react-hook-form'
export default function ContactForm() {
const { register, handleSubmit, formState: { errors } } = useForm()
const onSubmit = (data) => {
console.log(data)
// Send data to API
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Name</label>
<input {...register('name', { required: true })} />
{errors.name && <span>Name is required</span>}
</div>
<div>
<label>Email</label>
<input {...register('email', { required: true })} />
{errors.email && <span>Email is required</span>}
</div>
<button type="submit">Submit</button>
</form>
)
}
Output:
🔹 Validation Rules
Add validation rules directly to register function. React Hook Form supports required, min, max, pattern, and custom validation with clear error messages.
// components/SignupForm.jsx
'use client'
import { useForm } from 'react-hook-form'
export default function SignupForm() {
const { register, handleSubmit, formState: { errors } } = useForm()
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<div>
<input
{...register('username', {
required: 'Username is required',
minLength: {
value: 3,
message: 'Username must be at least 3 characters'
}
})}
placeholder="Username"
/>
{errors.username && <p>{errors.username.message}</p>}
</div>
<div>
<input
{...register('email', {
required: 'Email is required',
pattern: {
value: /^\S+@\S+$/i,
message: 'Invalid email address'
}
})}
placeholder="Email"
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<div>
<input
type="password"
{...register('password', {
required: 'Password is required',
minLength: {
value: 8,
message: 'Password must be at least 8 characters'
}
})}
placeholder="Password"
/>
{errors.password && <p>{errors.password.message}</p>}
</div>
<button type="submit">Sign Up</button>
</form>
)
}
🔹 Form with Server Actions
Integrate React Hook Form with Next.js Server Actions for seamless form submission. Handle validation on client and processing on server for secure data handling.
// app/actions.js
'use server'
export async function createUser(data) {
// Process form data
console.log('Creating user:', data)
return { success: true }
}
// components/UserForm.jsx
'use client'
import { useForm } from 'react-hook-form'
import { createUser } from '@/app/actions'
export default function UserForm() {
const { register, handleSubmit, formState: { isSubmitting } } = useForm()
const onSubmit = async (data) => {
const result = await createUser(data)
if (result.success) {
alert('User created!')
}
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} placeholder="Name" />
<input {...register('email')} placeholder="Email" />
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? 'Submitting...' : 'Submit'}
</button>
</form>
)
}
🔹 Watch Form Values
Monitor form field values in real-time with the watch function. Useful for conditional rendering, live previews, or dependent field validation.
// components/ConditionalForm.jsx
'use client'
import { useForm } from 'react-hook-form'
export default function ConditionalForm() {
const { register, watch } = useForm()
const accountType = watch('accountType')
return (
<form>
<select {...register('accountType')}>
<option value="personal">Personal</option>
<option value="business">Business</option>
</select>
{accountType === 'business' && (
<div>
<label>Company Name</label>
<input {...register('companyName')} />
</div>
)}
<button type="submit">Submit</button>
</form>
)
}
🔹 Reset and Default Values
Set default values and reset forms easily. Useful for edit forms, clearing after submission, or restoring initial state.
// components/EditForm.jsx
'use client'
import { useForm } from 'react-hook-form'
export default function EditForm({ user }) {
const { register, handleSubmit, reset } = useForm({
defaultValues: {
name: user.name,
email: user.email
}
})
const onSubmit = (data) => {
console.log(data)
// After successful update
reset() // Reset to default values
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('name')} />
<input {...register('email')} />
<button type="submit">Update</button>
<button type="button" onClick={() => reset()}>
Reset
</button>
</form>
)
}