Retour • 30/09/2024
Comment faire de bons formulaires en React ?
Écris par Melvyn Malherbe le 30/09/2024
Il y a plus de moyens de faire des formulaires en React que de frameworks JS. C'est pour ça que j'ai envie de parler d'un concept que j'ai, à l'époque, pris longtemps à comprendre : les formulaires en React.
Dans cet article, on va comprendre le problème d'utiliser des useState
en React, on va comparer les libraries disponibles ainsi que la façon la plus simple de gérer un formulaire.
Controlled, uncontrolled input ?
Arrêtons-nous sur cette simple définition.
Un controlled input, c'est un input qui est géré par un state. La valeur affichée est totalement liée au state.
const Controlled = () => {
return <input value="controlled" readOnly />;
};
const Uncontrolled = () => {
return <input defaultValue={'Uncontrolled'} />;
};
Si tu ne mets pas de readOnly, tu vas avoir un warning dans la console car tu n'as pas ajouté de onChange. L'utilisateur ne pourra pas modifier la valeur.
Le controlled ne peut pas être modifié. Le seul moyen de pouvoir le modifier est d'utiliser un useState React :
const Controlled = () => {
const [value, setValue] = useState('controlled');
return <input value={value} onChange={(e) => setValue(e.target.value)} />;
};
Ce qu'on est en train de faire ici c'est de contrôler la valeur du champ texte avec React. Mais qui contrôle cette valeur par défaut ?
La réponse c'est le DOM
! Il faut savoir que par défaut le DOM
gère totalement la valeur d'un champ texte. Le champ uncontrolled
a bien une valeur non ? Bah celle-ci est stockée et affichée par le DOM
.
Mais ce qu'on fait quand on contrôle un champ texte, c'est qu'on donne la charge à React de venir modifier la valeur quand l'utilisateur change la valeur du champ, voici ce qu'il se passe :
Clique sur le bouton "Ok, ensuite..." pour voir le comportement du composant
Voilà ce que React va devoir faire à chaque fois. Il va "repeindre" l'écran avec ta nouvelle valeur.
C'est ce qu'on appelle les inputs contrôlés.
Faire un formulaire simplement
Voici un exemple d'un formulaire contrôlé :
const MyForm = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const onSubmit = () => {
alert(`Submitted ${name} ${email}`);
};
return (
<form>
<input value={name} onChange={(e) => setName(e.target.value)} />
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<button onClick={onSubmit}>Submit</button>
</form>
);
};
Et un exemple d'un formulaire pas contrôlé :
const MyForm = () => {
const onSubmit = (event) => {
event.preventDefault();
const form = event.currentTarget;
const formData = new FormData(form);
const name = formData.get('name');
const email = formData.get('email');
alert(`Submitted ${name} ${email}`);
};
return (
<form className="flex flex-col gap-2 p-2" onSubmit={onSubmit}>
<input type="text" id="name" />
<input type="email" id="email" />
<button type="submit">Submit</button>
</form>
);
};
Ce que tu peux voir ici c'est qu'on utilise les fonctionnalités du DOM
c'est-à-dire les FormData
pour venir contrôler notre champ texte.
Cette méthode nous permet d'éviter les render
chaque fois que l'utilisateur change une valeur.
Un render c'est le fait que React exécute notre composant pour regarder le résultat. Je t'invite à aller voir ma vidéo YouTube :
Voici la différence, pour tester, change la valeur des champs. Quand le composant devient vert c'est qu'un re-render s'est produit :
Controlled
Uncontrolled
Teste les deux formulaires, avec le bouton submit.
Les deux fonctionnent mais l'un ne fait que de bipper vert. Chaque fois que le background devient vert c'est que le composant a rerender. Le lifecycle qu'on a vu avant se produit ici. Inutilement car, à droite, ça fonctionne pareil sans rerender.
Quand utiliser controlled ou uncontrolled ?
Tu peux utiliser controlled
quand :
- ✅ Tu as besoin de gérer la valeur liée au state et tu ne fais pas que de la lecture, mais aussi de l'écriture. Donc tu modifies le state en utilisant
setState
. Par exemple dans un AutoComplete. - ❌ Si tu souhaites juste effectuer une action quand tu changes la valeur de l'input il ne faut pas écouter la valeur avec un
useEffect
mais juste utiliser leonChange
pour effectuer des modifications. - ❌ Si tu souhaites juste lire la valeur de l'input, tu peux utiliser une
ref
. - ❌ Si tu souhaites faire un formulaire, utilise l'API de form ou react-use-form.
Pour la gestion d'erreur, par contre il est obligatoire d'utiliser un state. Mais attention, tu te retrouves vite avec des choses complexes et chiantes à gérer si tu fais tout à la main... Genre ce code :
const [errors, setErrors] = useState({ name: null, email: null });
const onSubmit = (e) => {
const formData = new FormData(form);
const name = formData.get('name');
const email = formData.get('email');
let errors = { name: null, email: null };
if (!name) errors.name = 'Name is required';
if (!email) errors.email = 'Email is required';
// email length
if (email.length > 50) errors.email = 'Email is too long';
if (email.length < 5) errors.email = 'Email is too short';
if (errors.name || errors.email) {
setErrors(errors);
return;
}
alert(name, email);
};
Sur l'échelle de l'enfer, ce code est à un bon niveau. C'est pour cette raison que je te recommande fortement d'utiliser react-use-form.
Conclusion
Nous avons vu la différence entre controlled
et uncontrolled
et nous avons compris le lifecycle d'un input controlled
. Nous avons pu voir quelles étaient leurs différences dans le cas d'un formulaire basique.
Nous savons maintenant quand utiliser ou ne pas utiliser controlled
ou uncontrolled
.
En règle générale, utiliser uncontrolled
est la meilleure option. Tu as de nombreux moyens d'en faire avec des références, des formData ou des librairies comme react-use-form
.
Un formulaire controlled
te sera utile uniquement pour un search input ou pour une donnée que tu souhaites contrôler...
Le meilleur moyen d'apprendre React !
Rejoins par développeurs, cette formation reçoit une note de 4.7 / 5 🚀
Reçois 12 leçons premium pour maîtriser React et faire partie des meilleurs
Petit quiz de fin ?
Faut-il utiliser un unctronolled ou controlled input quand on veut afficher une search bar qui serait debounce dans l'url ?
Que libraire utiliser quand on souhaites créer un formulaire compliqué avec des erreuzrs ?
Faut-il utiliser un formuilaire controlled ou uncontrolled quand on demande par exemple un username et qu'il y a qu'un seul champs ?