create-form
Set up hybrid client/server validated forms with Zod and React Hook Form. Use when creating forms with validation.
Installation
Suivez les instructions du dépôt pour votre agent. Consultez les fichiers et dépendances avant l’installation.
Voir la source ↗GuidesInstructions
Create Form
When to Use
- Creating any form with validation
- User asks to "add a form" or "create a form"
Critical Rule
// CORRECT - Use <form> with manual fetcher.submit()
<form onSubmit={handleSubmit(onSubmit)}>
// WRONG - Causes submission conflicts
<fetcher.Form onSubmit={handleSubmit(onSubmit)}>
Core Pattern
- Same Zod schema on client and server
- Client: Instant feedback with React Hook Form
-
Server: Security with
validateFormData() - Auto error sync: Server errors populate form fields
Quick Start
1. Schema (app/lib/validations.ts)
import { z } from 'zod';
export const contactFormSchema = z.object({
name: z.string().min(1, 'Name is required'),
email: z.string().email('Invalid email'),
});
export type ContactFormData = z.infer<typeof contactFormSchema>;
2. Server Action
import { validateFormData } from '~/lib/form-validation.server';
import { zodResolver } from '@hookform/resolvers/zod';
export async function action({ request }: Route.ActionArgs) {
const formData = await request.formData();
const { data, errors } = await validateFormData<ContactFormData>(
formData,
zodResolver(contactFormSchema)
);
if (errors) return data({ errors }, { status: 400 });
await processData(data!);
return redirect('/success');
}
3. Client Form
import { useFetcher } from 'react-router';
import { useValidatedForm } from '~/lib/form-hooks';
export default function ContactPage() {
const fetcher = useFetcher();
const { register, handleSubmit, formState: { errors } } = useValidatedForm({
resolver: zodResolver(contactFormSchema),
errors: fetcher.data?.errors,
});
const onSubmit = (data: ContactFormData) => {
const formData = new FormData();
formData.append('name', data.name);
fetcher.submit(formData, { method: 'POST' });
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<TextInput {...register('name')} error={errors.name?.message} />
<Button type="submit">Submit</Button>
</form>
);
}
Checklist
- Define Zod schema in
app/lib/validations.ts - Add server action with
validateFormData() - Use
useValidatedFormhook in component - Use
<form>(not<fetcher.Form>) withhandleSubmit
Templates
Full Reference
See .github/instructions/form-validation.instructions.md for:
- Field-level vs form-level errors
- Conditional validation
- File uploads
- Complex schema patterns
Exemples
Consultez les exemples du dépôt source.
Voir la source ↗Historique source
- Date d’indexation
- 2026-01-20
- Mise à jour de l’index
- 2026-01-26
- Branch
- main
Les dates concernent ce répertoire. Consultez le dépôt pour l’historique du code.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!