Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.chataigne.ai/llms.txt

Use this file to discover all available pages before exploring further.

Zod crée des schémas de validation qui s’intègrent avec React Hook Form. Un schéma = validation + types TypeScript automatiques.

Vue d’ensemble

Schéma de validation

Définir les règles de validation avec Zod

Hook de formulaire

Intégrer le schéma avec React Hook Form

Composant formulaire

Utiliser le hook dans un composant

Service de validation

Valider avant l’envoi au backend

Créer un schéma

On sépare les schémas par feature et par usage. Exemples d’organisation :
Pour les données métier principales :
product-schema.ts
import { z } from "zod";

export const productSchema = z.object({
  name: z.string().min(1, "Le nom est requis"),
  price: z.number().positive("Le prix doit être positif"),
  categoryId: z.string().min(1, "La catégorie est requise"),
  isVisible: z.boolean().default(true),
});

export type Product = z.infer<typeof productSchema>;

Hook de formulaire

Créez un hook personnalisé qui combine Zod et React Hook Form :
use-option-dialog-form.hook.ts
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import {
  optionDialogSchema,
  type OptionDialogForm,
} from "../validations/option-dialog.schema";

export function useOptionDialogForm(initialData?: Partial<OptionDialogForm>) {
  return useForm<OptionDialogForm>({
    resolver: zodResolver(optionDialogSchema),
    defaultValues: {
      name: "",
      minSelections: 0,
      maxSelections: null,
      ...initialData,
    },
  });
}
Le zodResolver connecte automatiquement la validation Zod avec React Hook Form.

Composant formulaire

Utilisez le hook dans votre composant :
OptionDialog.component.tsx
import { useOptionDialogForm } from "../hooks/use-option-dialog-form.hook";
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
} from "@/shared/components/ui/form";
import { Input } from "@/shared/components/ui/input";

export function OptionDialog({ onSubmit, initialData }) {
  const form = useOptionDialogForm(initialData);

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="name"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Nom de la liste d'options</FormLabel>
              <FormControl>
                <Input placeholder="Entrez le nom" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormField
          control={form.control}
          name="minSelections"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Sélections minimum</FormLabel>
              <FormControl>
                <Input
                  type="number"
                  min="0"
                  {...field}
                  onChange={(e) => field.onChange(Number(e.target.value))}
                />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
      </form>
    </Form>
  );
}

Validation dans le service

Validez les données avant de les envoyer au backend :
option.service.ts
import { optionDialogSchema } from "../validations/option-dialog.schema";
import { authClient } from "@/shared/services/backend-client.service";

export const createOption = async (formData: unknown) => {
  // Validation côté client
  const validatedData = optionDialogSchema.parse(formData);

  // Envoi au backend avec données validées
  return authClient.$fetch("/api/options", {
    method: "POST",
    body: validatedData,
  });
};
Utilisez .parse() pour une validation stricte qui lève une erreur si les données sont invalides.

Types de validation courants

// Validation de chaînes
z.string().min(1, "Requis")
z.string().email("Email invalide")
z.string().optional()
z.string().regex(/^[A-Z]+$/, "Majuscules uniquement")

Bonnes pratiques

1

Organisation des fichiers

Séparez les schémas par usage et par feature :
features/catalog/validations/
├── product-schema.ts          # Entité produit
├── product-dialog.schema.ts   # Formulaire création/édition
├── category-schema.ts         # Entité catégorie
└── catalog-dialog.schema.ts   # Formulaire catalog
2

Messages d'erreur clairs

Utilisez des messages en français, spécifiques et actionables : typescript z.string().min(2, "Le nom doit contenir au moins 2 caractères")
3

Validation dans les services

Toujours valider avec .parse() avant l’envoi au backend :
const validatedData = schema.parse(formData);
Cette approche garantit une validation cohérente et type-safe entre le formulaire et l’API.