React Hook Form
How to integrate React Checkbox Pro with React Hook Form and Zod validation
React Hook Form Integration
Learn how to integrate React Checkbox Pro with React Hook Form for form management and validation.
Installation
Install dependencies
npm install react-hook-form @hookform/resolvers zod
# or
yarn add react-hook-form @hookform/resolvers zod
# or
pnpm add react-hook-form @hookform/resolvers zod
Import required components
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Checkbox, CheckboxGroup } from "react-checkbox-pro";
Form Schema
First, define your form schema using Zod:
import * as z from "zod";
export const checkboxFormSchema = z.object({
acceptTerms: z.boolean().refine(val => val === true, {
message: "You must accept the terms and conditions"
}),
notifications: z.object({
email: z.boolean(),
sms: z.boolean(),
push: z.boolean()
}).refine(data => Object.values(data).some(val => val), {
message: "You must select at least one notification method"
}),
interests: z.array(z.string()).min(1, {
message: "Please select at least one area of interest"
}),
subscription: z.enum(["free", "pro", "enterprise"]).optional(),
marketing: z.boolean().optional(),
});
export type CheckboxFormData = z.infer<typeof checkboxFormSchema>;
Complete Example
Here's a comprehensive example showing different ways to use React Checkbox Pro with React Hook Form:
import { useForm, Controller } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Checkbox, CheckboxGroup } from "react-checkbox-pro";
import { checkboxFormSchema, type CheckboxFormData } from "@/lib/validations/checkbox-form.schema";
export default function FormExample() {
const {
handleSubmit,
control,
formState: { errors },
watch,
} = useForm<CheckboxFormData>({
resolver: zodResolver(checkboxFormSchema),
defaultValues: {
acceptTerms: false,
notifications: {
email: false,
sms: false,
push: false,
},
interests: [],
subscription: undefined,
marketing: false,
},
});
const onSubmit = (data: CheckboxFormData) => {
console.log("Form submitted:", data);
};
return (
<div className="min-h-screen bg-gray-50 dark:bg-gray-900 p-8">
<div className="max-w-2xl mx-auto space-y-8">
<div className="p-6 rounded-lg shadow-sm bg-white dark:bg-gray-800">
<h1 className="text-2xl font-bold mb-6">Registration Form</h1>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
{/* Terms and Conditions */}
<div className="space-y-2">
<Controller
name="acceptTerms"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.acceptTerms}
errorMessage={errors.acceptTerms?.message}
>
I accept the terms and conditions
</Checkbox>
)}
/>
</div>
{/* Notification Preferences */}
<div className="space-y-4">
<h2 className="text-lg font-semibold">Notification Preferences</h2>
<div className="space-y-2">
<Controller
name="notifications.email"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.notifications}
>
Email notifications
</Checkbox>
)}
/>
<Controller
name="notifications.sms"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.notifications}
>
SMS notifications
</Checkbox>
)}
/>
<Controller
name="notifications.push"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.notifications}
>
Push notifications
</Checkbox>
)}
/>
{errors.notifications && (
<p className="text-sm text-red-500 mt-1">
{errors.notifications.message}
</p>
)}
</div>
</div>
{/* Areas of Interest */}
<div className="space-y-4">
<h2 className="text-lg font-semibold">Areas of Interest</h2>
<Controller
name="interests"
control={control}
render={({ field }) => (
<CheckboxGroup
value={field.value}
onChange={field.onChange}
error={!!errors.interests}
>
<Checkbox value="technology">Technology</Checkbox>
<Checkbox value="design">Design</Checkbox>
<Checkbox value="business">Business</Checkbox>
<Checkbox value="marketing">Marketing</Checkbox>
</CheckboxGroup>
)}
/>
{errors.interests && (
<p className="text-sm text-red-500">
{errors.interests.message}
</p>
)}
</div>
{/* Subscription Type */}
<div className="space-y-4">
<h2 className="text-lg font-semibold">Subscription Type</h2>
<Controller
name="subscription"
control={control}
render={({ field }) => (
<div className="space-y-2">
<Checkbox
checked={field.value === "free"}
onChange={() => field.onChange("free")}
color="default"
>
Free Plan
</Checkbox>
<Checkbox
checked={field.value === "pro"}
onChange={() => field.onChange("pro")}
color="primary"
>
Pro Plan
</Checkbox>
<Checkbox
checked={field.value === "enterprise"}
onChange={() => field.onChange("enterprise")}
color="secondary"
>
Enterprise Plan
</Checkbox>
</div>
)}
/>
</div>
{/* Marketing Preferences */}
<div className="space-y-2">
<Controller
name="marketing"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
color="success"
>
I want to receive marketing emails
</Checkbox>
)}
/>
</div>
<button type="submit">Submit</button>
</form>
</div>
</div>
</div>
);
}
Usage Patterns
Single Checkbox
<Controller
name="acceptTerms"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.acceptTerms}
errorMessage={errors.acceptTerms?.message}
>
Accept Terms
</Checkbox>
)}
/>
Checkbox Group
<Controller
name="interests"
control={control}
render={({ field }) => (
<CheckboxGroup
value={field.value}
onChange={field.onChange}
error={!!errors.interests}
>
<Checkbox value="option1">Option 1</Checkbox>
<Checkbox value="option2">Option 2</Checkbox>
</CheckboxGroup>
)}
/>
Nested Fields
<Controller
name="notifications.email"
control={control}
render={({ field }) => (
<Checkbox
checked={field.value}
onChange={field.onChange}
error={!!errors.notifications}
>
Email notifications
</Checkbox>
)}
/>
Best Practices
-
Form Setup:
- Use Zod for type-safe schema validation
- Define proper default values
- Handle form submission appropriately
-
Error Handling:
- Display field-specific error messages
- Show group-level validation errors
- Use proper error styling
-
Performance:
- Memoize callbacks when needed
- Use form context for complex forms
- Avoid unnecessary re-renders
-
Accessibility:
- Maintain proper form structure
- Include proper ARIA attributes
- Ensure keyboard navigation works
Last updated on