Files
MaksTinyWorkshop 9b7af9f1b0 Refonte Structure
2026-03-25 08:34:19 +01:00

4.6 KiB
Raw Permalink Blame History

Frontend — Patterns : Forms

Extrait de la base de connaissance Lead_tech. Voir knowledge/frontend/patterns/README.md pour l'index complet.


Pattern : Formulaire robuste avec validation et erreurs explicites

Synthèse

  • Objectif : garantir des formulaires fiables, compréhensibles et maintenables.
  • Contexte : toute interface avec saisie utilisateur et règles métier.
  • Quand l'utiliser : dès qu'un formulaire dépasse un simple champ isolé.
  • Quand l'éviter : formulaires ultra-simples sans validation réelle.

Analyse

  • Avantages :
    • UX claire (l'utilisateur sait quoi corriger)
    • Moins d'erreurs silencieuses
    • Base saine pour tests et accessibilité
  • Limites / vigilance :
    • Peut sembler verbeux sans discipline
    • Risque de duplication si mal factorisé

Validation

  • Validé le : 25-01-2026
  • Contexte technique : Front-end agnostique, API HTTP

Implémentation (exemple minimal)

- Validation côté client (format, champs requis)
- Validation côté serveur (règles métier)
- Mapping explicite des erreurs serveur → champs UI
- Aucun submit silencieux

Checklist

  • Messages d'erreur compréhensibles et localisés
  • Validation client + serveur cohérente
  • Focus automatique sur le champ en erreur
  • États loading / disabled gérés
  • Tests sur cas valides et invalides

Pattern : Toggle optimiste avec rollback (React Server Action)

Synthèse

  • Objectif : masquer la latence serveur sur un toggle boolean en mettant à jour l'UI immédiatement, avec rollback en cas d'erreur.
  • Contexte : toggles boolean (visibilité, disponibilité, settings) où la latence doit être masquée.
  • Quand l'utiliser : toggles sans besoin de re-fetcher l'entité entière après mutation.
  • Quand l'éviter : mutations qui retournent des données complexes → préférer le pattern "Server Action retournant l'entité".

Validation

  • Validé le : 21-03-2026
  • Contexte technique : React / Next.js App Router — app-template-resto

Implémentation

const [optimistic, setOptimistic] = useState(initialValue);

async function handleToggle() {
  const prev = optimistic;
  setOptimistic(!prev);          // update immédiat
  try {
    await toggleAction(!prev);
    router.refresh();            // synchronise le Server Component parent
  } catch {
    setOptimistic(prev);         // rollback si erreur
  }
}

Pattern : Server Action retournant l'entité — élimination de router.refresh() sur create/edit

Synthèse

  • Objectif : mettre à jour l'état local directement avec les données réelles retournées par le serveur, sans round-trip SSR supplémentaire.
  • Contexte : liste d'items managée côté client (useState) avec création et modification via Server Actions.
  • Quand l'utiliser : create et edit d'entités dans une liste. Plus performant que toggle optimiste + router.refresh().
  • Quand l'éviter : simples toggles boolean → le pattern optimiste avec rollback suffit.

Analyse

  • Avantages vs toggle optimiste + router.refresh() :
    • Zéro aller-retour SSR supplémentaire (~500ms2s économisés sur mobile)
    • État local garanti cohérent avec la DB (données réelles, pas calculées localement)
    • Pas de flash de rechargement
  • Limites / vigilance :
    • revalidatePath reste nécessaire pour invalider le cache des pages publiques

Validation

  • Validé le : 22-03-2026
  • Contexte technique : React / Next.js App Router — app-template-resto story 3.8

Implémentation

// Repository — retourne l'entité complète
export async function createItem(tenantId: string, data: Input): Promise<ItemRow> {
  return prisma.item.create({ data: { tenantId, ...data }, select: { ...fullSelect } });
}

// Action — retourne la donnée au client
export async function createItemAction(formData: FormData): Promise<ItemRow> {
  const actor = await requireOwner();
  const item = await createItem(actor.tenantId, input);
  revalidatePath("/dashboard/..."); // invalider cache pages publiques
  return item; // ← clé : retourner l'entité
}

// Client — mise à jour locale sans round-trip SSR
const created = await createItemAction(formData);
setItems((prev) => [...prev, created]); // pas de router.refresh()

Pour les entités avec relations : utiliser un helper findItemById(tenantId, id) appelé après la mutation pour retourner la forme complète avec les relations résolues.