• 8 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/8/24

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

Maîtrisez les événements en React

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 : un événement est une réaction à une action émise par l'utilisateur, comme le clic sur un bouton ou la saisie d'un texte dans un formulaire.

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

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

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

  • 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'utiliser addEventListener.

Testons ça dès maintenant dans notre code. Dans  components/PlantItem.js, je vais déclarer une fonction  handleClick  qui vient faire un log dans notre console :

function 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 : yeeeees ! Ç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 :

function handleClick(plantName) {
    alert(`Vous voulez acheter 1 ${plantName} ? Très bon choix 🌱✨`)
}

Mais si je clique, ça ne marche pas :

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

En effet, React passe par défaut un objet (que nous aborderons dans quelques minutes), 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 !
Et voilà ! 😎

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 :

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

j'obtiens ça :

Le console.log nous dévoile que cet événement est un événement synthétique.
Le console.log de notre événement

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

Ça nous donne beaucoup d'informations, n'est-ce pas ? Mais à quoi ça correspond ? 🤔

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()  . Si vous avez besoin de rafraîchir vos connaissances sur  preventDefault   et  stopPropagation, je vous renvoie sur le chapitre événements de l'excellent cours "Apprenez à programmer avec JavaScript".

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 : la manière contrôlée et la manière non contrôlée. J'aborderai assez rapidement la manière non contrôlée, parce qu'elle nécessite moins d'implication de React, et que React encourage l'utilisation des formulaires contrôlés.

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

Je vous fais une petite démo d'un formulaire non contrôlé. Sur notre app, directement dans  App.js, 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 :

function 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.

Contrôlez vos formulaires

Le state local nous permet de garder des informations. Ces informations sont spécifiques à un composant et elles proviennent d'une interaction que l'utilisateur a eue avec le composant.

Donc 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'

function 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 ? 🤔

Comprenez les avantages des formulaires contrôlés

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 :

const isInputError = inputValue.includes('f') 

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 :

function 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.

Sachez qu'il existe également des bibliothèques qui vous permettent de gérer les formulaires et leur validation aussi proprement que possible, par exemple le très bon outil react-hook-form.

Et voilà, vous êtes maintenant équipé pour interagir avec vos utilisateurs grâce aux événements et aux formulaires. 😎

Exercez-vous

Banner Exercez-vous

Vous allez maintenant pouvoir mettre tout ça en application. Comme d'habitude, vous trouverez la base de code pour commencer l'exercice sur P2C5-Begin.

Cette fois-ci, voilà une petite to do de ce que vous pouvez faire pour enrichir notre app :

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

    • "Cette plante requiert peu/modérement/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  inputValue   et  setInputValue   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.”

La solution se trouve sur la branche P2C5-Solution.

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'utiliser  addEventListener.

  • 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 ! 🚀

Example of certificate of achievement
Example of certificate of achievement