Picture of the author
Published on

Simplifiez vos formulaires avec React Hook Form

Authors
Gérer les formulaires dans React peut rapidement devenir complexe, surtout avec plusieurs champs, des règles de validation, et la gestion de l'état du formulaire. Dans ce tutoriel, nous allons explorer comment React Hook Form simplifie la gestion des formulaires. Nous commencerons par un formulaire simple d'enregistrement d'utilisateur et l'améliorerons progressivement avec React Hook Form, en décomposant chaque étape pour rester clair et pratique.

Pourquoi la gestion des formulaire est compliquée ?

Les formulaires sont essentiels pour l'interaction utilisateur, mais gérer leur état et validation dans React peut être difficile. Il est souvent nécessaire d'écrire beaucoup de code pour gérer les événements onChange, onSubmit, et la logique de validation.

C'est ici qu'intervient React Hook Form. Cette bibliothèque fournit un ensemble de hooks pour gérer l'état et la validation des formulaires avec un minimum de code. Voici ses avantages :

  • Léger : Réduit le code.
  • Performances optimisées : Minimise les re-rendus pour de meilleures performances.
  • Extensible : S'intègre facilement avec des bibliothèques d'interface utilisateur ou des validations personnalisées.
  • API simple : Intuitive et facile à utiliser, même pour les débutants.


Configuration du projet

D'abord, configurons une application React de base et installons React Hook Form.

1# Initialiser un projet React
2npx create-react-app guideco-form
3cd guideco-form

Création d'un formulaire simple sans React Hook Form

Créons un simple formulair sans React Hook Form pour mettre en évidence les limites.

1import React, { useState } from 'react'
2
3const ConnectionForm = () => {
4    const [formData, setFormData] = useState({email: "", password: "" });
5
6    const handleChange = (e) => {
7      const { name, value } = e.target;
8      setFormData({ ...formData, [name]: value });
9    };
10  
11    const handleSubmit = (e) => {
12      e.preventDefault();
13      console.log(formData);
14    };
15  
16    return (
17      <div className="flex items-center justify-center">
18        <form className="bg-white p-6 rounded shadow-md w-96" onSubmit={handleSubmit}>
19            <label className="block mb-2">
20                Email:
21                <input
22                    type="email"
23                    name="email"
24                    value={formData.email}
25                    onChange={handleChange}
26                    className="w-full mt-1 p-2 border rounded"
27                />
28            </label>
29    
30            <label className="block mb-4">
31                Password:
32                <input
33                    type="password"
34                    name="password"
35                    autoComplete='on'
36                    value={formData.password}
37                    onChange={handleChange}
38                    className="w-full mt-1 p-2 border rounded"
39                />
40            </label>
41    
42            <button
43                type="submit"
44                className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
45            >
46                Register
47            </button>
48        </form>
49      </div>
50    );
51}
52
53export default ConnectionForm

react basic form management

Dans le code ci-dessus, nous n'avons que 02 champs de saisie, email et password ainsi qu'un bouton de soumission.

Ces champs sont reliés à un gestionnaire (handleChange) afin de pouvoir mettre à jour le state (formData) en fonction de la saisie de l'utilisateur.

La méthode handleSubmit permet d'afficher les données saisies dans le formulaire dans la console.

Ce code, tant bien qu'éfficace deviendra compliqué au fur et à mesure que nous ajouterons des champs, et des validations telles que la validation des champs obligatoires, la validation de la longueur minimale, la validation du mot de passe, la validation du champ e-mail et afficher les messages d'erreur correspondants.

Par exemple, imaginons que nous voulons un champ pour le numéro de téléphone, un champs pour l'adresse et également certaines vérification avant la soumission de notre formulaire. la fonction handleSubmite deviendrait vite difficile à maintenir :

1const [formData, setFormData] = useState({
2  name: "",
3  email: "",
4  password: "",
5  phone: "",
6  address: ""
7});
8
9const handleSubmit = (e) => {
10  e.preventDefault();
11  let hasError = false;
12
13  // Validations des champs
14  if (!formData.email) {
15    alert("Email is required");
16    hasError = true;
17  } else if (!/\S+@\S+\.\S+/.test(formData.email)) {
18    alert("Invalid email format");
19    hasError = true;
20  }
21
22  if (!formData.password) {
23    alert("Password is required");
24    hasError = true;
25  } else if (formData.password.length < 8) {
26    alert("Password must be at least 8 characters long");
27    hasError = true;
28  }
29
30  if (!formData.phone) {
31    alert("Phone number is required");
32    hasError = true;
33  } else if (!/^\d{10}$/.test(formData.phone)) {
34    alert("Phone number must be 9 digits");
35    hasError = true;
36  }
37
38  if (!formData.address) {
39    alert("Address is required");
40    hasError = true;
41  } else if (formData.address.length < 5) {
42    alert("Address must be at least 5 characters long");
43    hasError = true;
44  }
45
46  if (!hasError) {
47    console.log("Form submitted successfully!", formData);
48  }
49};
50

Introduction à React Hook Form

Voyons maintenant comment React Hook Form peut simplifier cela. Nous allons refactoriser le formulaire précédent en utilisant le hook useForm.

Installons tout d'abord la librairie react-hook-form :

1# Installation de React Hook Form
2npm install react-hook-form

react-hook-form met à notre disposition divers methodes pour la gestion des formulaires dont useForm qui fera l'objet de notre attention.

Importons le hook useForm dans notre code comme suit:

1import { useForm } from "react-hook-form";

Simple formulaire avec react-hook-form

Refactorisons le code précédent afin de gérer l'état de notre formulaire avec react-hook-form

1import React from 'react';
2import { useForm } from "react-hook-form";
3
4const ConnectionForm = () => {
5    const {
6        register,
7        handleSubmit,
8        formState: { errors },
9    } = useForm();
10
11    const onSubmit = (data) => {
12        console.log(data); // Log the submitted data
13    };
14  
15    
16  
17    return (
18      <div className="flex items-center justify-center">
19        <form
20            className="bg-white p-6 rounded shadow-md w-96"
21            onSubmit={handleSubmit(onSubmit)}
22        >
23
24            {/* Email Field */}
25            <label className="block mb-2">
26                Email:
27                <input
28                    type="email"
29                    {...register("email", { required: "Email is required" })}
30                    className="w-full mt-1 p-2 border rounded"
31                />
32            </label>
33
34            {/* Password Field */}
35            <label className="block mb-4">
36                Password:
37                <input
38                    type="password"
39                    {...register("password", { required: "Password is required" })}
40                    className="w-full mt-1 p-2 border rounded"
41                    autoComplete='on'
42                />
43            </label>
44
45            <button
46                type="submit"
47                className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
48            >
49                Register
50            </button>
51        </form>
52      </div>
53    );
54}
55
56export default ConnectionForm

creusons un peu plus dans le code ci-haut :

  • register: c'est une fonction fournie par le hook useForm. Nous pouvons l'assigner à chaque champ de saisie afin que le react-hook-form puisse suivre les changements de la valeur du champ de saisie :
1<input
2    type="text"
3    className="w-full mt-1 p-2 border rounded"
4    {...register("name", { required: "Name is required" })}
5/>
  • handleSubmit : est une fonction que nous pouvons appeler lors afin de gerer la soumission du formulaire.
  • errors : est une propriété imbriquée dans l'objet formState qui contiendra les erreurs de validation, s'il y en a.

Ajout de la validation :

Ajoutons maintenant la validation des champs obligatoires et de la longueur minimale aux champs de saisie.

Pour ce faire, nous pouvons passer un objet à la fonction register en tant que second paramètre, comme ceci :

1// ...
2<input
3    type="text"
4    className="w-full mt-1 p-2 border rounded"
5    {...register("name", { required: "Name is required" })}
6/>
7
8// ...
9<input
10    type="email"
11    {...register("email", { required: true, maxLength: 6 })}
12    className="w-full mt-1 p-2 border rounded"
13/>

Le code complet ressemble à ceci :

1import React from 'react';
2import { useForm } from "react-hook-form";
3
4const ConnectionForm = () => {
5    const {
6        register,
7        handleSubmit,
8        formState: { errors },
9    } = useForm();
10
11    const onSubmit = (data) => {
12        console.log(data);
13    };
14  
15  
16    return (
17      <div className="flex items-center justify-center">
18        <form
19            className="bg-white p-6 rounded shadow-md w-96"
20            onSubmit={handleSubmit(onSubmit)}
21        >
22
23            {/* Email Field */}
24            <label className="block mb-2">
25                Email:
26                <input
27                    type="email"
28                    {...register("email", {
29                        required: true,
30                        pattern: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/
31                    })}
32                    className="w-full mt-1 p-2 border rounded"
33                />
34                {errors.email && errors.email.type === "required" && (
35                    <p className="text-red-500">Email is required.</p>
36                )}
37                {errors.email && errors.email.type === "pattern" && (
38                    <p className="text-red-500">Email is not valid.</p>
39                )}
40            </label>
41
42            {/* Password Field */}
43            <label className="block mb-4">
44                Password:
45                <input
46                    type="password"
47                    {...register("password", {
48                        required: true,
49                        minLength: 6
50                    })}
51                    className="w-full mt-1 p-2 border rounded"
52                    autoComplete='on'
53                />
54                {errors.password && errors.password.type === "required" && (
55                    <p className="text-red-500">Password is required.</p>
56                )}
57                {errors.password && errors.password.type === "minLength" && (
58                    <p className="text-red-500">
59                    Password should be at-least 6 characters.
60                    </p>
61                )}
62            </label>
63
64            <button
65                type="submit"
66                className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
67            >
68                Register
69            </button>
70        </form>
71      </div>
72    );
73}
74
75export default ConnectionForm
react form using useForm

Dans le code ci-haut, nous avons changé la validation de l'email et du mot de passe:

1{...register("email", {
2    required: "Email is required.",
3    pattern: {
4        value: /^[^@ ]+@[^@ ]+\.[^@ .]{2,}$/,
5        message: "Email is not valid."
6    }
7})}

nous avons directement fourni le message d'erreur que nous voulons afficher lors de l'ajout de la validation elle-même.
ous affichons le message d'erreur en utilisant la propriété message disponible dans l'objet errors pour chaque champ de saisie comme ceci :

1{errors.password && errors.password.type === "required" && (
2    <p className="text-red-500">Password is required.</p>
3)}
4{errors.password && errors.password.type === "minLength" && (
5    <p className="text-red-500">
6    Password should be at-least 6 characters.
7    </p>
8)}


Conclusion

En intégrant react-hook-form étape par étape, nous avons réduit le code standard, ajouté une validation puissante et rendu notre formulaire beaucoup plus facile à mettre à l'échelle. Essayez-le dans vos projets et voyez combien de temps vous gagnerez !