React form hook test
This is a test post to test the React form hook.
- asdas
- asdalksdmlak sdlak sdlka sdlk asdlka sdlk asdlk asld alsdk alksd laksd laks dlaks dlak sdlka sdlka sdlka sdlka sdlka sdlk asdlka sdlk asdlk asdlk asdlk asdlk asldk alsdk laksd
- asdasd
- asdasd
- asdasdasd
- asdasdas
Form Test Project
Exploring advanced React Hook Form patterns with Zod discriminated unions, dynamic field arrays, and type-safe form handling in TypeScript.
A React TypeScript form project exploring React Hook Form with Zod validation and internationalization.
🚀 Live Demo
Quick Start
Prerequisites
- Node.js (v18+)
- PNPM package manager
Setup
# Install dependencies
pnpm install
# Start development server
pnpm dev
The app will be available at http://localhost:5173
Build
# Build for production
pnpm build
# Preview production build
pnpm preview
Key Takeaways
This project explored various patterns and best practices for complex form handling in React. Here are the main lessons learned:
1. Type-safe Form Hooks
Create smart aliases for useOrderForm and useOrderFormState to build the entire form in a type-safe manner. This ensures proper TypeScript inference throughout the form components.
2. Automatic Re-rendering with register
Fields registered with register() automatically re-render when their own values change (e.g., user input, programmatic updates, resets). Use useWatch() to re-render components when other fields change.
3. Zod Discriminating Unions
Use Zod's discriminating unions for conditional validation. For example, company fields that are required for business customers but not for individual customers.
Bonus: Fields not in the active union branch are automatically excluded from the submit data. So when customerType is "individual", the company field won't be included in the final form data - no manual cleanup needed!
// Real example from the project
const customerSchema = z.discriminatedUnion('customerType', [
z.object({
customerType: z.literal('individual'),
phone: phoneValidation.or(z.string().length(0)), // Optional
}),
z.object({
customerType: z.literal('business'),
company: z.string().min(1), // Required
phone: phoneValidation, // Required
}),
]);
4. Custom Error Handling
Handle custom validation errors in the zodResolver, not in the Zod schema itself. This provides better integration with React Hook Form's error system.
5. Leverage useFieldArray
Use useFieldArray extensively for dynamic array operations. It handles adding, removing, and reordering items efficiently with proper form state management.
6. useFieldArray Context Sharing
Important: When using useFieldArray in multiple components, ensure you're using the exact same reference. Put it in a context provider, otherwise it won't work properly. Items will be added to the state but won't appear in the UI.
7. Conditional Rendering with useWatch
Use useWatch() for smart conditional rendering based on form state. This works perfectly with discriminated unions:
const watch = useOrderFormWatch();
const isVisible = watch.customerType === "business";
if (!isVisible) {
return null;
}
return (
<Field required={true}>
<Field.Label>Company</Field.Label>
<Input {...register("company")} />
</Field>
);