
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.
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 !
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 :

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().
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 non contrôlée,
et la manière contrôlée.
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.
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 QuestionFormIci, 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 ê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 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 !