7
Module 7
Les formulaires
Le hook 'useRef' et le DOM
Contrairement à 'useState', qui est conçu pour gérer des états et déclencher des re-rendus lorsqu'ils changent, 'useRef est un hook de React permettant de maintenir des valeurs qui ne nécessitent pas de re-rendu lorsque modifiées.
Les fonctions principales de 'useRef'
Références du DOM : 'useRef' est couramment utilisé pour obtenir des références à des éléments du DOM, ce qui permet des manipulations directes (comme mettre le focus sur un champ d'entrée ou lire la valeur d'un élément).
Valeurs Persistantes : 'useRef' peut également être utilisé pour stocker des valeurs ou des objets qui doivent persister entre les rendus mais ne devraient pas provoquer de re-rendus lorsqu'ils changent.
Contenu Mutable : Contrairement à 'useState', qui provoque un re-rendu lorsque l'état change, 'useRef' permet de modifier son contenu sans affecter le rendu du composant.
Structure de 'useRef'
'useRef' renvoie un objet avec une propriété 'current'. Cette propriété contient la référence ou la valeur que l'on souhaite stocker. On peut lire ou modifier cette propriété sans déclencher de re-rendu.
Information
Nous illustrerons le fonctionnement de 'useRef' dans la section suivante avec la notion de formulaire non contrôlé.
Formulaire non contrôlé et validation
Dans cette section, nous allons créer un formulaire où les valeurs des champs d'entrée sont gérées directement par le DOM au lieu d'être contrôlées par l'état du composant. Ce type de formulaire en React est appelé 'formulaire non contrôlé'. En effet, nous utiliserons les références (useRef) pour accéder aux valeurs des éléments du formulaire, car les modifications de ces valeurs n'entraînent pas de re-rendu du composant.
Reprenons notre application 'biblio-app' puis, créons un nouveau composant nommé 'FormNonControlle.jsx'. Ce nouveau composant contiendra un formulaire non contrôlé que nous importerons dans le composant 'Contact'.
Formulaire non contrôlé sans validation
/components/FormNonControlle.jsx
'use client'
import styles from './FormNonControlle.module.css';
import { useRef } from 'react';
export default function FormNonControlle() {
const nomRef = useRef(null); // Créer une référence pour le champ de nom
const courrielRef = useRef(null); // Créer une référence pour le champ courriel
const handleSubmit = (event) => {
event.preventDefault(); // Empêche la soumission par défaut du formulaire
const nom = nomRef.current.value; // Obtenir la valeur du champ de nom
const courriel = courrielRef.current.value; // Obtenir la valeur du champ courriel
console.log(`Nom: ${nom}, Courriel: ${courriel}`);
};
return <>
<form onSubmit={handleSubmit}>
<div>
<label>Nom:</label>
<input type="text" ref={nomRef} /> {/* Champ de texte avec une référence */}
</div>
<div>
<label>Email:</label>
<input type="email" ref={courrielRef} /> {/* Champ de texte avec une référence */}
</div>
<button type="submit">Envoyer</button>
</form>
</>;
}
Remarque
Nous pouvons constater qu'une référence a été créée pour chaque champ du formulaire grâce au composant 'useRef'. Par la suite, la liaison a été faite grâce à l'attribut 'ref' de React dans chaque champ. Il suffit donc d'importer ce composant dans 'Contact.jsx' pour l'utiliser.
/components/Contact.jsx
import FormNonControlle from "./FormNonControlle"
export default function Contact() {
return <>
<div>
Formulaire non contrôlé
<FormNonControlle/>
</div>
</>;
}
Formulaire non contrôlé avec validation
/components/FormNonControlle.jsx
'use client'
import styles from './Form.module.css';
import { useRef, useState } from 'react';
export default function FormNonControlle() {
const nomRef = useRef(null); // Créer une référence pour le champ de nom
const courrielRef = useRef(null); // Créer une référence pour le champ courriel
const [erreurNom, setErreurNom] = useState('');
const [erreurCourriel, setErreurCourriel] = useState('');
const [envoiReussi, setEnvoiReussi] = useState(false);
const courrielRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // Expression régulière pour valider le courriel
const handleSubmit = (event) => {
event.preventDefault(); // Empêche la soumission par défaut du formulaire
const nom = nomRef.current.value; // Obtenir la valeur du champ de nom
const courriel = courrielRef.current.value; // Obtenir la valeur du champ de courriel
let erreur = false;
if (!nom) {
setErreurNom("Ce champ doit être rempli");
erreur = true;
} else {
setErreurNom('');
}
if (!courriel || !courrielRegex.test(courriel)) {
setErreurCourriel("Ce courriel est invalide");
erreur = true;
} else {
setErreurCourriel('');
}
if (erreur) {
setEnvoiReussi(false);
return;
}
setEnvoiReussi(true);
};
return <>
<form onSubmit={handleSubmit} className={styles.form}>
<div>
<label>Nom:
<input type="text" ref={nomRef} /> {/* Champ de texte avec une référence */}
{erreurNom &&
<div className={styles.erreur}>{erreurNom}</div>
}
</label>
</div>
<div>
<label>Email:
<input type="email" ref={courrielRef} /> {/* Champ de texte avec une référence */}
{erreurCourriel &&
<div className={styles.erreur}>{erreurCourriel}</div>
}
</label>
</div>
<button type="submit">Envoyer</button>
{envoiReussi &&
<div className={styles.result}>
Informations envoyées avec succès. Nom = {nomRef.current.value} et Courriel = {courrielRef.current.value}
</div>
}
</form>
</>;
}
Remarque
Dans ce nouveau exemple, nous avons ajouté des 'div' à chaque label, pour afficher l'erreur sur le champ qui lui est associé. Les contenus de ces 'div' sont gérés par le hook 'useState'.
/components/Form.module.css
.form {
max-width: 20rem;
padding: 1rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
.form label {
display: flex;
flex-direction: column;
}
.result{
color: green;
}
.erreur {
color: #a00;
}
Formulaire contrôlé et validation
Dans cette section, nous allons créer un formulaire où les valeurs des champs d'entrée sont gérées par par l'état (useState) du composant. Ce type de formulaire en React est appelé 'formulaire contrôlé'.
Reprenons notre application 'biblio-app' puis, créons un nouveau composant nommé 'FormControlle.jsx'. Ce nouveau composant contiendra un formulaire contrôlé que nous importerons dans le composant 'Contact'.
Formulaire contrôlé sans validation
/components/FormControlle.jsx
'use client'
import styles from './Form.module.css';
import { useState } from 'react';
export default function FormControlle() {
const [nom, setNom] = useState(''); // variable pour le champ de nom
const [courriel, setCourrel] = useState(''); // variable pour le champ courriel
const handleNom = (event) => setNom(event.target.value); //Pour modifier le nom
const handleCourriel = (event) => setCourrel(event.target.value); //pour modifier le courriel
const handleSubmit = (event) => {
event.preventDefault(); // Empêche la soumission par défaut du formulaire
console.log(`Nom: ${nom}, Courriel: ${courriel}`); // Affichage du nom et courriel
};
return <>
<form onSubmit={handleSubmit} className={styles.form}>
<div>
<label>Nom:</label>
<input
type="text"
name='nom'
value={nom}
onChange={handleNom}
/>
</div>
<div>
<label>Email:</label>
<input
type="email"
name='courriel'
value={courriel}
onChange={handleCourriel}
/>
</div>
<button type="submit">Envoyer</button>
</form>
</>;
}
Remarque
Contrairement à l'exemple précédent, nous pouvons constater que 'useRef' a été remplacé par 'useState' pour manipuler les valeurs des champs. De plus, de nouvelles fonctions ont été créées pour gérer la valeur du champ à chaque changement d'état. Il suffit donc d'importer ce composant dans 'Contact.jsx' comme précédemment, afin de l'utiliser.
Formulaire contrôlé avec validation
Travail à faire
En suivant la logique de la section précédente, ajoutez de la validation à notre formulaire contrôlé.
Formulaire avec la bibliothèque 'react-hook-form'
'react-hook-form'est une bibliothèque construite pour gérer les formulaires dans les applications React. Elle se concentre sur la simplicité, la performance et l'utilisation de hooks (introduits avec React 16.8) pour fournir une manière efficace de gérer les formulaires et la validation des champs.
Pour l'illustrer, nous allons créer un nouveau composant dans notre application 'biblio-app'. Ce composant sera nommé 'FormHook.jsx'. Mais avant de continuer, il va falloir installer la bibliothèque 'react-hook-form' avec la commande suivante :
Terminal
npm install react-hook-form/components/FormHook.jsx
'use client'
import styles from './Form.module.css'
import { useForm } from 'react-hook-form'
export default function FormHook() {
const {
register,
handleSubmit,
watch,
formState: { errors }
} = useForm({
defaultValues: {
nom: '',
courriel: ''
}
});
const nom = watch('nom');
return <>
<form className={styles.form}
onSubmit={handleSubmit()}>
<label>
Nom:
<input
type="text"
{...register("nom",
{
required: 'Champ obligatoire',
minLength: { value: 4, message: "min 4 caractères" }
})
}
placeholder='votre nom' />
<div className={styles.erreur}>{errors.nom?.message}</div>
</label>
<div>Nom : {nom}</div>
<label>
Courriel:
<input
type="email"
{...register("courriel",
{
required: 'Champ obligatoire',
pattern: {
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
message: 'Courriel non valide'
}
})
}
placeholder='votre courriel'
/>
<div className={styles.erreur}>{errors.courriel?.message}</div>
</label>
<button type="submit">Envoyer</button>
</form>
</>
}
Dans cet exemple, le hook 'useForm' initialise le formulaire. Le champ 'register' est utilisé pour enregistrer les éléments de formulaire(nom et courriel). Les erreurs de validation sont gérées via 'formState.errors'. 'handleSubmit' déclenche une fonction de soumission qui traite les données lorsque le formulaire est soumis avec succès.
Il ne reste plus qu'à l'importer dans le composant 'Contact.jsx' afin l'utiliser.
Envoyer des courriels
Envoyer des courriels directement côté client présente des défis majeurs en matière de sécurité et de fiabilité. Les navigateurs ne permettent pas aux pages web côté client d'envoyer directement des courriels en raison de restrictions de sécurité, notamment pour éviter le spam et les abus.
Cependant, vous pouvez intégrer des services d'envoi d'e-mails côté client en utilisant des API tierces qui fournissent des fonctionnalités d'envoi d'e-mails. Ces API peuvent être utilisées pour envoyer des requêtes HTTP depuis le client vers le serveur de l'API tiers, qui ensuite envoie l'e-mail.
Parmi les API pouvant être utilisées pour envoyer des courriels côté client, on peut citer : EmailJS, Formspree, SMTPJS, Email Octopus, SendGrid et bien d'autres. Dans le cadre de ce cours, nous utiliserons EMAILJS.
DEMO
La vidéo qui va suivre nous présentera comment utiliser EmailJS pour envoyer des courriels.
Code source
Important
Avant d'executer la commande 'npm run dev', bien vouloir exécuter la commande 'npm i'.
Travail à faire