codelynx.dev
🇫🇷🇬🇧

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.

JSX
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 :

JSX
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é :

JSX
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é :

JSX
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 le onChange 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 :

JSX
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 ?

BeginReact

Cours React gratuit

Accède à des exercices, des vidéos et bien plus sur React dans la formation "BeginReact" 👇