Fermer

juin 13, 2024

Validation du formulaire Next.js à l’aide des actions du serveur par Zod / Blogs / Perficient

Validation du formulaire Next.js à l’aide des actions du serveur par Zod / Blogs / Perficient


La validation côté serveur protège contre les données invalides et malveillantes, garantissant ainsi l’intégrité et la sécurité des données. Dans cet article, nous verrons comment utiliser Zod, une bibliothèque de validation déclarative JavaScript, pour la validation de formulaire côté serveur dans une application Next.js. Nous explorerons également comment gérer les échecs de validation fournis par le serveur.

Hypothèses

Ce blog suppose que Next.js est configuré localement. Si ce n’est pas le cas, veuillez suivre le guide de configuration officiel sur le site Web Next.js : Guide de configuration Next.js.

Conditions préalables

Dans cet article de blog, j’utilise :
– Next.js 14.x
– CSS Tailwind
– Tapuscrit
– Zod (un package NPM pour la déclaration de schéma et la bibliothèque de validation pour TypeScript)

Pourquoi ajouter une validation côté serveur ?

Supposons que nous ayons créé un formulaire avec Next.js et ajouté une validation côté client. Ce formulaire affiche une validation lorsque le JavaScript du navigateur est activé mais pas lorsqu’il est désactivé. Sans validation côté serveur, le formulaire ne lancera pas la validation et soumettra le formulaire. Pour empêcher les utilisateurs de saisir des données invalides, nous utilisons la validation côté serveur.

Voici une capture d’écran montrant comment désactiver JavaScript pour un site particulier dans Chrome :

Chrome Js désactiver

Vous trouverez ci-dessous une capture d’écran de ma base de code. Une fois que vous avez configuré Suivant.jsil vous suffit de créer un Composants dossier et un action.ts fichier, qui doit être parallèle au Composants dossier.

Validation du formulaire Next.js à l'aide des actions du serveur par Zod

Création du Inscription.tsx Composant

Dans le Composants dossier, créer Inscription.tsx:

"use client";

import { FC, useState } from "react";
import { useFormState } from "react-dom";
import { createNewUser } from "@/action";

interface FormErrorProps {
errors?: string[];
}

const FormError: FC<FormErrorProps> = ({ errors }) => {
if (!errors?.length) return null;
return (
<div className="p-2">
{errors.map((err, index) => (
<p className="text-tiny text-red-400 list-item" key={index}>
{err}
</p>
))}
</div>
);
};

const SignUp: FC = () => {
const [date, setDate] = useState(new Date());
const [state, formAction] = useFormState(
createNewUser.bind(null, { date: date?.toISOString() }),
{ success: false }
);

return (
<form action={formAction} className="flex flex-col gap-y-2">
<label htmlFor="name">SignUp</label>
<input id="name" name="name" className="border-2" />
<FormError errors={state?.errors?.name} />

<input id="email" name="email" className="border-2" />
<FormError errors={state?.errors?.email} />

<input id="password" name="password" className="border-2" />
<FormError errors={state?.errors?.password} />

<button type="submit" className="border-2">
Create
</button>
</form>
);
};

export default SignUp;

Note: Tous les éléments des champs de formulaire peuvent rester décochés et nous n’avons pas besoin d’utiliser les fonctionnalités de React. utiliserÉtat crochet pour l’état du formulaire. Dans ce composant, nous utilisons le hook de formulaire React utiliserFormState, qui prend une fonction comme premier argument. Dans notre exemple, nous passons une fonction écrite en action.tsx et l’objet d’état pour le formulaire :

const [state, formAction] = useFormState(
createNewUser.bind(null, { date: date?.toISOString() }),
{ success: false }
);

Créer un nouvel utilisateur Fonction

Il nous manque encore createNewUser fonction utilisée dans l’attribut action du formulaire. Nous allons créer cette fonction dans le action.ts déposer. Il s’agit d’une action du serveur.

Les actions du serveur transmises à l’attribut d’action du formulaire reçoivent les données supplémentaires, Erreurs d’inscriptionet Données de formulaire objet du formulaire comme premier argument, qui encapsule toutes les données du formulaire. Nous utiliserons cet objet pour obtenir la valeur des champs de saisie et valider avec Zod. Dans action.tsj’ai écrit le schéma Zod pour la validation du nom, de l’e-mail et du mot de passe :

const userSchema = z.object({
name: z.string().trim().min(3, "Name must be at least 3 characters long!").max(18),
email: z.string().email("Email is invalid"),
password: z
.string()
.min(8, "Password is too short!")
.max(20, "Password is too long")
.regex(passwordValidation, {
message: "Your password is not valid",
})
.optional(),
});

Vérification des données du formulaire avec safeParse()

Dans action.tsnous vérifions les données du formulaire avec safeParse(). Si une erreur se produit, renvoie un objet avec {succès : faux, erreurs : result.error.flatten().fieldErrors}ou en cas de succès, revenez {succès : vrai}.

actions.ts

"use server";

import { z } from "zod";

/* TypeScript-first schema validation with static type inference */
const passwordValidation = new RegExp(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
);

const userSchema = z.object({
name: z.string().trim().min(3, "Name must be at least 3 characters long!").max(18),
email: z.string().email("Email is invalid"),
password: z
.string()
.min(8, "Password is too short!")
.max(20, "Password is too long")
.regex(passwordValidation, {
message: "Your password is not valid",
})
.optional(),
});

export interface SignUpErrors {
errors?: {
name?: string[];
email?: string[];
password?: string[];
};
success: boolean;
}

export const createNewUser = async (
date: any,
data: SignUpErrors,
formData: FormData
): Promise<SignUpErrors> => {
const result = userSchema.safeParse({
name: formData.get("name"),
email: formData.get("email"),
password: formData.get("password"),
});
if (result.success) {
/* Database action like creating a user */
return { success: true };
}
return { success: false, errors: result.error.flatten().fieldErrors };
};

Note: Nous utilisons utiliserFormState dans Inscription.tsx. Il ne fonctionne que dans un composant client, mais aucun de ses parents n’est marqué « utiliser le client », ce sont donc des composants serveur par défaut.

Conclusion

Dans cet article, nous avons abordé le concept des actions serveur, leurs avantages par rapport aux routes API classiques et l’utilisation des actions serveur dans les applications Next.js. Les actions serveur améliorent l’expérience utilisateur et le processus de développement en réduisant le code JavaScript côté client, en augmentant l’accessibilité et en permettant les modifications des données côté serveur. Si vous souhaitez créer des applications Web modernes avec Next.js, les actions serveur sont un outil indispensable. Expérimentez avec les actions du serveur pour améliorer vos applications. Exécutez le prochain analyseur de bundle régulièrement dans le cadre de votre processus de développement pour suivre les changements dans la taille du bundle et détecter toute régression.






Source link