Interagissez avec vos composants grâce aux événements

Si vous avez déjà manipulé du JavaScript, vous êtes sûrement déjà familier avec les événements. Bon, vous avez quand même droit à un petit rappel :

Bonne nouvelle pour vous : avec sa syntaxe pratique et concise, React facilite énormément la gestion des événements du DOM. 

Familiarisez-vous avec la syntaxe des événements

Quelques caractéristiques de la déclaration d'un événement en React :

  • l'événement s'écrit dans une balise en camelCase ;

  • vous déclarez l'événement à capter, et lui passez entre accolades la fonction à appeler ;

  • contrairement au JS, dans la quasi totalité des cas, vous n'avez pas besoin d'utiliseraddEventListener.

Testons ça dès maintenant dans notre code.

Dans  components/PlantItem.jsx, je vais déclarer une fonction fléchée  handleClick  qui vient faire un log dans notre console :

const handleClick = () => {
  console.log('✨ Ceci est un clic ✨')
}

 On ajoute maintenant  onClick={handleClick}  dans la balise  li  du composant  PlantItem.

On a donc :

<li className='lmj-plant-item' onClick={handleClick}>
  <img className='lmj-plant-item-cover' src={cover} alt={`${name} cover`} />
  {name}
  <div>
    <CareScale careType='water' scaleValue={water} />
    <CareScale careType='light' scaleValue={light} />
  </div>
</li>

J'ouvre la console : ça fonctionne comme prévu ! 

Je vais pousser cet exercice un peu plus loin : on va déclencher une alerte qui affiche le nom de la plante sur laquelle on a cliqué.

On passe donc  plantName  en paramètre de  handleClick  comme ici :

<li className='lmj-plant-item' onClick={handleClick}>
  <img className='lmj-plant-item-cover' src={cover} alt={`${name} cover`} />
  {name}
  <div>
    <CareScale careType='water' scaleValue={water} />
    <CareScale careType='light' scaleValue={light} />
  </div>
</li>

Mais si je clique, ça ne marche pas :

Aucune de nos plantes ne s'appelle 1 [object Object] !

En effet, React passe par défaut un objet (que nous aborderons bientôt), mais ici, nous voulons lui spécifier notre propre argument.

Pour cela, c'est très simple : on déclare une fonction directement dans  onClick (les fonctions fléchées sont très pratiques pour ça).

Cette fonction appellera  handleClick  en lui passant  name  en paramètre.

Donc on a :

onClick={() => handleClick(name)}

Essayez pour voir !

Découvrez les événements synthétiques

Donc, je vous parlais de l'objet que React passe par défaut en paramètre aux fonctions indiquées en callback des événements. Voyons voir à quoi ça ressemble. 

Si je récupère le paramètre dans  handleClick :

const handleClick = (e) => {
  console.log('✨ Ceci est mon event :', e)
}

…J'obtiens ça :

Le console.log de notre événement
Le console.log de notre événement

Allez-y, essayez de le faire par vous-même !

Il s'agit en fait d'un événement synthétique. Pour faire bref, il s'agit de la même interface que pour les événements natifs du DOM, sauf qu'ils sont compatibles avec tous les navigateurs.

Pratique, n'est-ce pas ?

Vu qu'il s'agit de la même interface que pour les événements natifs du DOM, est-ce qu'on a aussi accès à  preventDefault  et  stopPropagation  ?

Tout à fait ! Vous pouvez utiliser ces méthodes avec le paramètre récupéré dans la fonction passée à l'événement.

Dans notre cas, vous auriez pu faire  e.preventDefault().

Simplifiez votre création de formulaires avec React

En React, la gestion des formulaires est simplifiée : on a accès à la valeur très facilement, qu'il s'agisse d'un input  checkbox  , d'un  textarea  , ou encore d'un  select  avec  onChange.

Il existe deux grandes manières de gérer les formulaires :

  1. la manière non contrôlée,

  2. et la manière contrôlée.

1. Déléguez le contrôle : les formulaires non contrôlés

Voyons ensemble une rapide démonstration d'un formulaire non contrôlé.

  • Sur notre app, directement dans  App.jsx, je mets un composant  QuestionForm  que je vais déclarer dans un fichier à part.

  • Nous allons ajouter un champ pour une question.

Donc pour ça je crée un form, qui englobe mon input :

<form onSubmit={handleSubmit}>
  <input type='text' name='my_input' defaultValue='Tapez votre texte' />
  <button type='submit'>Entrer</button>
</form>

Et pour handleSubmit, cela donne :

const handleSubmit = (e) => {
  e.preventDefault()
  alert(e.target['my_input'].value)
}

Vous voyez que React me permet de préciser une  defaultValue  à mon champ  input. Ici, j'appelle  preventDefault, sinon le  submit  rafraîchirait la page.

Et j'ai bien mon alerte qui se déclenche. 

Plutôt simple, n'est-ce pas ? Vous déléguez le travail à votre DOM.

Effectivement, les formulaires non contrôlés nous permettent de ne pas avoir à gérer trop d'informations. Mais cette approche est un peu moins "React", parce qu'elle ne permet pas de tout faire.

À la place, vous pouvez utiliser les composants contrôlés.

2. Contrôlez vos formulaires

Je vais créer ma variable  inputValue  et la fonction qui va permettre de changer sa valeur dans le state local avec  useState  .

Sachez juste que la ligne de code ci-dessous me permet de déclarer l'état initial pour  inputValue  et la fonction correspondante pour la modifier, et de lui préciser la valeur par défaut "Posez votre question ici" :

const [inputValue, setInputValue] = useState("Posez votre question ici")

J'ai donc mon  QuestionForm  comme ci-dessous :

import { useState } from 'react'

const QuestionForm = () => {
  const [inputValue, setInputValue] = useState('Posez votre question ici')
  
  return (
    <div>
      <textarea
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      />
    </div>
  )
}

export default QuestionForm

Ici, je passe une fonction en callback à  onChange  pour qu'elle sauvegarde dans mon state local la valeur de mon input. J'accède à la valeur tapée dans l'input avec  e.target.value.

inputValue  a maintenant accès au contenu de mon input à tout moment. Je peux donc créer un bouton qui déclenche une alerte qui affiche le contenu de mon input, comme ici :

<div>
  <textarea
    value={inputValue}
    onChange={(e) => setInputValue(e.target.value)}
  />
  <button onClick={() => alert(inputValue)}>Alertez moi 🚨</button>
</div>

Et ça marche bien !

C'est bien beau d'avoir accès à la valeur de mon input, mais pourquoi ? 

Eh bien, cela permet d'interagir directement avec la donnée renseignée par l'utilisateur. Vous pouvez donc afficher un message d'erreur si la donnée n'est pas valide, ou bien la filtrer en interceptant une mauvaise valeur.

Si nous décidons qu'il n'est pas autorisé d'utiliser la lettre "f" (bon oui, c'est un peu bizarre), eh bien nous pouvons déclarer une variable :

{isInputError && (
  <div>🔥 Vous n'avez pas le droit d'utiliser la lettre "f" ici.</div>
)}

et afficher ou non un message d'erreur en fonction de ce booléen :

{isInputError && (
  <div>🔥 Vous n'avez pas le droit d'utiliser la lettre "f" ici.</div>
)}

De la même manière, nous pouvons intercepter une mauvaise valeur entrée par l'utilisateur. Pour cela, il faut déclarer une fonction intermédiaire :

const checkValue = (value) => {
  if (!value.includes('f')) {
    setInputValue(value)
  }
}

et on applique la modification dans notre fonction callback :

onChange={(e) => checkValue(e.target.value)}

Ici, vous aurez beau marteler votre touche F autant de fois que vous voudrez, la valeur ne s'inscrira pas dans votre input.

Vous ne vous en rendez peut-être pas compte pour l'instant, mais ça vous laisse une très grande liberté quant aux validations que vous voulez créer ; et en tant que développeur, c'est vraiment très puissant.

Super, je connais les deux méthodes, mais quand utiliser le composant contrôlé et quand utiliser sa version non contrôlée ?!

Eh bien cela dépend des cas. À vous de voir selon vos contraintes. Quand vous avez un composant rapide à faire, qui n'intègre aucune complexité, un input non contrôlé peut faire l'affaire. À l'inverse, si vous avez des vérifications à faire, il vaudra sûrement mieux passer par un composant contrôlé. Pour ma part, j'ai vu beaucoup plus de composants contrôlés dans les codebases que j'ai pu voir.

À vous de jouer !

Vous êtes maintenant équipé pour interagir avec vos utilisateurs grâce aux événements et aux formulaires. Vous allez pouvoir mettre tout ça en application. 

Créez une alerte qui se déclenche au clic sur le composant  CareScale  qui devra dire :

  • "Cette plante requiert peu/modérément/beaucoup de lumière/d'arrosage" en fonction de la donnée correspondante ;

  • s'il s'agit d'un composant  CareScale  de type "water" ou de type "light".

Vous trouverez dans la base de code un nouveau composant : Footer. Vous devez y ajouter :

  • un input pour récupérer le mail de l'utilisateur, en appliquant la méthode de composant contrôlé. La syntaxe du state que nous avons utilisée dans ce chapitre pour inputValueetsetInputValue qui utilise  useState  est d'ailleurs déjà écrite dans la base de code ;

  • l'événement blur (quand on clique en dehors du champ) qui déclenche une alerte si  inputValue  ne contient pas le caractère "@". Cette alerte devra préciser "Attention, il n'y a pas d'@, ceci n'est pas une adresse valide."

En résumé

  • En React, un événement s'écrit dans une balise en camelCase, et on lui passe la fonction à appeler.

  • Contrairement au JS, dans la quasi totalité des cas, vous n'avez pas besoin d'utiliseraddEventListener.

  • React passe un événement synthétique en paramètre des fonctions de callBack. Cet événement synthétique est similaire à un événement passé en natif dans le DOM, sauf qu'il est compatible avec tous les navigateurs.

  • Il existe deux grandes manières de gérer les formulaires : les formulaires contrôlés ou non contrôlés. L'utilisation des formulaires contrôlés est recommandée.

  • Les formulaires contrôlés sauvegardent la valeur des champs dans le state local, et accèdent à la data entrée par l'utilisateur avec onChange.

  • Les formulaires contrôlés permettent de filtrer le contenu, ou d'afficher un message d'erreur en fonction de la data qui est entrée par l'utilisateur.

Nous voilà à nouveau à la fin d'une partie. Vous allez pouvoir vérifier vos acquis dans le quiz. Puis, une fois que ce sera fait, vous allez pouvoir vous lancer dans le state avec React !

Et si vous obteniez un diplôme OpenClassrooms ?
  • Formations jusqu’à 100 % financées
  • Date de début flexible
  • Projets professionnalisants
  • Mentorat individuel
Trouvez la formation et le financement faits pour vous