Quick Start Guide
Get up and running with Hero Hook Form in 5 minutes.
This guide will help you create your first form. For a detailed comparison of different form building patterns, see the Form Patterns Comparison guide.
Installation
Install Hero Hook Form and its peer dependencies:
npm install @rachelallyson/hero-hook-form zod @hookform/resolversPeer Dependencies: Make sure you also have react, react-dom, react-hook-form, and @heroui/react installed. These are required peer dependencies.
Your First Form
Create a simple contact form in just a few lines:
import { ZodForm, FormFieldHelpers } from "@rachelallyson/hero-hook-form";
import { z } from "zod";
const schema = z.object({
email: z.string().email(),
name: z.string().min(2),
});
export default function ContactForm() {
return (
<ZodForm
config={{
schema,
fields: [
FormFieldHelpers.input("name", "Name"),
FormFieldHelpers.input("email", "Email", "email"),
],
}}
onSubmit={(data) => console.log(data)}
/>
);
}Expected Result: Invalid inputs show error messages; valid submission logs typed data.
Optional: Wrap Your App
For global form defaults and styling, wrap your app with the provider:
import { HeroHookFormProvider } from "@rachelallyson/hero-hook-form";
export function App() {
return (
<HeroHookFormProvider>
<YourForms />
</HeroHookFormProvider>
);
}The provider is optional but recommended for consistent styling and default configurations across all forms.
Form Building Patterns
Hero Hook Form supports multiple patterns. Choose the one that fits your style:
Method 1: Helper Functions (Recommended)
Best for: Most use cases. Simple, explicit, and easy to read.
import { FormFieldHelpers } from "@rachelallyson/hero-hook-form";
const fields = [
FormFieldHelpers.input("firstName", "First Name"),
FormFieldHelpers.input("lastName", "Last Name"),
FormFieldHelpers.input("email", "Email", "email"),
FormFieldHelpers.textarea("message", "Message"),
FormFieldHelpers.select("country", "Country", [
{ label: "Select a country", value: "" },
{ label: "United States", value: "us" },
{ label: "Canada", value: "ca" },
]),
FormFieldHelpers.checkbox("newsletter", "Subscribe to newsletter"),
];Method 2: Builder Pattern
Best for: Complex forms with many fields. Fluent API with method chaining.
import { createBasicFormBuilder } from "@rachelallyson/hero-hook-form";
const fields = createBasicFormBuilder()
.input("firstName", "First Name")
.input("lastName", "Last Name")
.input("email", "Email", "email")
.textarea("message", "Message")
.select("country", "Country", [
{ label: "Select a country", value: "" },
{ label: "United States", value: "us" },
{ label: "Canada", value: "ca" },
])
.checkbox("newsletter", "Subscribe to newsletter")
.build();Method 3: Common Fields
Best for: Quick prototyping. Pre-built field collections.
import { CommonFields, FormFieldHelpers } from "@rachelallyson/hero-hook-form";
const fields = [
...CommonFields.personal(), // firstName, lastName, email
FormFieldHelpers.textarea("message", "Message"),
...CommonFields.terms(), // newsletter, terms
];Not sure which pattern to use? Check out the Form Patterns Comparison guide for a detailed comparison.
Advanced Features
Type-Inferred Forms
import { defineInferredForm, field } from "@rachelallyson/hero-hook-form";
const form = defineInferredForm({
name: field.string("Name").min(2),
email: field.email("Email"),
age: field.number("Age").min(18),
newsletter: field.boolean("Subscribe to newsletter"),
});
// Use the form
<ZodForm config={form} onSubmit={handleSubmit} />Dynamic Forms
import { ConditionalField, FieldArrayField } from "@rachelallyson/hero-hook-form";
const fields = [
FormFieldHelpers.input("name", "Name"),
FormFieldHelpers.checkbox("hasPhone", "I have a phone number"),
ConditionalField({
name: "phone",
label: "Phone Number",
type: "input",
condition: (values) => values.hasPhone,
}),
FieldArrayField({
name: "addresses",
fields: [
FormFieldHelpers.input("street", "Street"),
FormFieldHelpers.input("city", "City"),
],
addButtonText: "Add Address",
}),
];Custom Validation
import { z } from "zod";
const schema = z.object({
password: z.string().min(8),
confirmPassword: z.string(),
}).refine(data => data.password === data.confirmPassword, {
message: "Passwords don't match",
path: ["confirmPassword"],
});Form Layouts
Vertical Layout (Default)
<ZodForm
config={{ schema, fields }}
layout="vertical"
spacing="4"
/>Grid Layout
<ZodForm
config={{ schema, fields }}
layout="grid"
columns={2}
spacing="4"
/>Horizontal Layout
<ZodForm
config={{ schema, fields }}
layout="horizontal"
spacing="4"
/>Error Handling
Client-Side Validation
const schema = z.object({
email: z.string().email("Please enter a valid email"),
name: z.string().min(2, "Name must be at least 2 characters"),
});Server-Side Errors
import { applyServerErrors } from "@rachelallyson/hero-hook-form";
const handleSubmit = async (data) => {
try {
await submitToServer(data);
} catch (error) {
// Apply server errors to form
applyServerErrors(form, error.fieldErrors);
}
};Custom Error Display
<ZodForm
config={{ schema, fields }}
errorDisplay="toast" // or "modal", "inline", "none"
onError={(errors) => console.log("Validation errors:", errors)}
/>Performance Optimization
Debounced Validation
import { useDebouncedValidation } from "@rachelallyson/hero-hook-form";
function MyComponent() {
const { debouncedValue, isDebouncing } = useDebouncedValidation(
value,
{ delay: 300 }
);
// Use debouncedValue for expensive operations
}Memoized Components
import { memo } from "react";
const MyField = memo(({ name, label }) => {
return <InputField name={name} label={label} />;
});Testing
Form Test Utilities
import { createFormTestUtils } from "@rachelallyson/hero-hook-form";
const testUtils = createFormTestUtils(form);
// Test form submission
await testUtils.submitForm();
// Get field value
const fieldValue = testUtils.getField("fieldName");
// Set field value
testUtils.setFieldValue("fieldName", "new value");Cypress Integration
import { simulateFormSubmission } from "@rachelallyson/hero-hook-form/cypress";
cy.get('[data-testid="form"]').then(simulateFormSubmission);Next Steps
Now that you’ve created your first form, explore more features:
- Form Patterns Comparison - Choose the right pattern for your needs
- Dynamic Forms Guide - Learn about conditional fields and field arrays
- Error Handling Guide - Master validation and error management
- API Reference - Explore the complete API
- Recipes - Copy-paste examples for common patterns
- FAQ - Find answers to common questions