v19.2Latest

Répondre aux événements

React vous permet d’ajouter desgestionnaires d’événementsà votre JSX. Les gestionnaires d’événements sont vos propres fonctions qui seront déclenchées en réponse à des interactions comme un clic, un survol, la focalisation sur des champs de formulaire, etc.

Vous apprendrez
  • Différentes façons d’écrire un gestionnaire d’événements
  • Comment transmettre la logique de gestion d’événements depuis un composant parent
  • Comment les événements se propagent et comment les arrêter

Ajouter des gestionnaires d’événements

Pour ajouter un gestionnaire d’événements, vous allez d’abord définir une fonction puis latransmettre comme propà la balise JSX appropriée. Par exemple, voici un bouton qui ne fait encore rien :

Vous pouvez lui faire afficher un message lorsqu’un utilisateur clique en suivant ces trois étapes :

  1. Déclarez une fonction appeléehandleClickà l’intérieurde votre composantButton.
  2. Implémentez la logique à l’intérieur de cette fonction (utilisezalertpour afficher le message).
  3. AjoutezonClick={handleClick}au JSX du<button>.

Vous avez défini la fonctionhandleClickpuis l’aveztransmise comme propau<button>.handleClickest ungestionnaire d’événements.Les fonctions gestionnaires d’événements :

  • Sont généralement définiesà l’intérieurde vos composants.
  • Ont des noms qui commencent parhandle, suivi du nom de l’événement.

Par convention, il est courant de nommer les gestionnaires d’événements avechandlesuivi du nom de l’événement. Vous verrez souventonClick={handleClick},onMouseEnter={handleMouseEnter}, etc.

Alternativement, vous pouvez définir un gestionnaire d’événements en ligne dans le JSX :

Ou, plus concisément, en utilisant une fonction fléchée :

Tous ces styles sont équivalents. Les gestionnaires d’événements en ligne sont pratiques pour les fonctions courtes.

Piège

Les fonctions passées aux gestionnaires d’événements doivent être transmises, pas appelées. Par exemple :

transmettre une fonction (correct)appeler une fonction (incorrect)
<button onClick={handleClick}><button onClick={handleClick()}>

La différence est subtile. Dans le premier exemple, la fonctionhandleClickest transmise comme gestionnaire d’événementonClick. Cela indique à React de la mémoriser et de n’appeler votre fonction que lorsque l’utilisateur clique sur le bouton.

Dans le second exemple, les()à la fin dehandleClick()déclenchent la fonctionimmédiatementpendant lerendu, sans aucun clic. C’est parce que le JavaScript à l’intérieur desaccolades { et } du JSXs’exécute tout de suite.

Lorsque vous écrivez du code en ligne, le même piège se présente d’une manière différente :

transmettre une fonction (correct)appeler une fonction (incorrect)
<button onClick={() => alert('...')}><button onClick={alert('...')}>

Transmettre du code en ligne comme ceci ne déclenchera pas l’action au clic—il se déclenche à chaque rendu du composant :

Si vous souhaitez définir votre gestionnaire d’événements en ligne, enveloppez-le dans une fonction anonyme comme ceci :

Plutôt que d’exécuter le code à chaque rendu, cela crée une fonction à appeler ultérieurement.

Dans les deux cas, ce que vous voulez transmettre est une fonction :

  • <button onClick={handleClick}>transmet la fonctionhandleClick.
  • <button onClick={() => alert('...')}>transmet la fonction() => alert('...').

En savoir plus sur les fonctions fléchées.

Lire les props dans les gestionnaires d’événements

Comme les gestionnaires d’événements sont déclarés à l’intérieur d’un composant, ils ont accès aux props du composant. Voici un bouton qui, lorsqu’on clique dessus, affiche une alerte avec sa propmessage :

Cela permet à ces deux boutons d'afficher des messages différents. Essayez de modifier les messages qui leur sont passés.

Passer des gestionnaires d'événements en tant que props

Souvent, vous voudrez que le composant parent spécifie le gestionnaire d'événements d'un composant enfant. Prenons l'exemple des boutons : selon l'endroit où vous utilisez un composantButton, vous pourriez vouloir exécuter une fonction différente — peut-être une qui joue un film et une autre qui télécharge une image.

Pour ce faire, passez une prop que le composant reçoit de son parent en tant que gestionnaire d'événements, comme ceci :

Ici, le composantToolbaraffiche unPlayButtonet unUploadButton:

  • PlayButtonpassehandlePlayClicken tant que proponClick au Buttonà l'intérieur.
  • UploadButtonpasse() => alert('Uploading!')en tant que proponClick au Buttonà l'intérieur.

Enfin, votre composantButtonaccepte une prop appeléeonClick. Il passe cette prop directement au<button>natif du navigateur aveconClick={onClick}. Cela indique à React d'appeler la fonction passée lors du clic.

Si vous utilisez unsystème de design, il est courant que des composants comme les boutons contiennent des styles mais ne spécifient pas le comportement. Au lieu de cela, des composants commePlayButtonetUploadButtontransmettront les gestionnaires d'événements vers le bas.

Nommer les props des gestionnaires d'événements

Les composants natifs comme<button>et<div>ne prennent en charge que lesnoms d'événements du navigateurcommeonClick. Cependant, lorsque vous créez vos propres composants, vous pouvez nommer leurs props de gestionnaire d'événements comme vous le souhaitez.

Par convention, les props des gestionnaires d'événements doivent commencer paron, suivi d'une lettre majuscule.

Par exemple, la proponClickdu composantButtonaurait pu s'appeleronSmash:

Dans cet exemple,<button onClick={onSmash}>montre que le<button>natif du navigateur (en minuscules) a toujours besoin d'une prop appeléeonClick, mais le nom de la prop reçue par votre composant personnaliséButtondépend de vous !

Lorsque votre composant prend en charge plusieurs interactions, vous pourriez nommer les props des gestionnaires d'événements selon des concepts spécifiques à l'application. Par exemple, ce composantToolbarreçoit les gestionnaires d'événementsonPlayMovieetonUploadImage :

Remarquez comment le composantAppn'a pas besoin de savoirce queToolbarfera aveconPlayMovieouonUploadImage. C'est un détail d'implémentation deToolbar. Ici,Toolbarles transmet comme gestionnairesonClick à ses Button, mais il pourrait plus tard aussi les déclencher via un raccourci clavier. Nommer les props d'après des interactions spécifiques à l'application commeonPlayMovievous donne la flexibilité de changer leur utilisation ultérieurement.

Remarque

Assurez-vous d'utiliser les balises HTML appropriées pour vos gestionnaires d'événements. Par exemple, pour gérer les clics, utilisez<button onClick={handleClick}>au lieu de<div onClick={handleClick}>. Utiliser un véritable<button>du navigateur active les comportements intégrés comme la navigation au clavier. Si vous n'aimez pas le style par défaut du navigateur pour un bouton et que vous voulez qu'il ressemble plus à un lien ou à un autre élément d'interface, vous pouvez y parvenir avec CSS.En savoir plus sur l'écriture de balisage accessible.

Propagation des événements

Les gestionnaires d'événements intercepteront également les événements provenant des enfants éventuels de votre composant. On dit qu'un événement « remonte » ou « se propage » dans l'arbre : il commence à l'endroit où l'événement s'est produit, puis remonte dans l'arbre.

Cette<div>contient deux boutons. La<div>etchaque bouton ont leurs propres gestionnairesonClick. Selon vous, quels gestionnaires s'exécuteront lorsque vous cliquerez sur un bouton ?

Si vous cliquez sur l'un ou l'autre bouton, sononClicks'exécutera en premier, suivi du<div>parentonClick. Deux messages apparaîtront donc. Si vous cliquez sur la barre d'outils elle-même, seul le<div>parentonClicks'exécutera.

Piège

Tous les événements se propagent dans React saufonScroll, qui ne fonctionne que sur la balise JSX à laquelle vous l'attachez.

Arrêter la propagation

Les gestionnaires d'événements reçoivent unobjet événementcomme seul argument. Par convention, il est généralement appelée, pour « event » (événement). Vous pouvez utiliser cet objet pour lire des informations sur l'événement.

Cet objet événement vous permet également d'arrêter la propagation. Si vous voulez empêcher un événement d'atteindre les composants parents, vous devez appelere.stopPropagation()comme le fait ce composantButton :

Lorsque vous cliquez sur un bouton :

  1. React appelle le gestionnaireonClickpassé au<button>.
  2. Ce gestionnaire, défini dansButton, effectue les actions suivantes :
    • Appellee.stopPropagation(), empêchant la propagation ultérieure de l'événement.
    • Appelle la fonctiononClick, qui est une prop transmise par le composantToolbar.
  3. Cette fonction, définie dans le composantToolbar, affiche l'alerte propre au bouton.
  4. Comme la propagation a été arrêtée, le gestionnaire<div>parentonClick nes'exécute pas.

Grâce àe.stopPropagation(), cliquer sur les boutons n'affiche désormais qu'une seule alerte (provenant du<button>) au lieu des deux (provenant du<button> et du <div>parent de la barre d'outils). Cliquer sur un bouton n'est pas la même chose que cliquer sur la barre d'outils qui l'entoure, donc arrêter la propagation est logique pour cette interface.

Deep Dive
Événements de phase de capture

Passer des gestionnaires comme alternative à la propagation

Remarquez comment ce gestionnaire de clic exécute une ligne de codepuisappelle la proponClicktransmise par le parent :

Vous pourriez ajouter plus de code à ce gestionnaire avant d'appeler le gestionnaire d'événementonClickparent. Ce modèle offre unealternativeà la propagation. Il permet au composant enfant de gérer l'événement, tout en permettant au composant parent de spécifier un comportement supplémentaire. Contrairement à la propagation, ce n'est pas automatique. Mais l'avantage de ce modèle est que vous pouvez clairement suivre toute la chaîne de code qui s'exécute à la suite d'un événement.

Si vous comptez sur la propagation et qu'il est difficile de retracer quels gestionnaires s'exécutent et pourquoi, essayez plutôt cette approche.

Empêcher le comportement par défaut

Certains événements du navigateur ont un comportement par défaut associé. Par exemple, un événement de soumission de<form>, qui se produit lorsqu'un bouton à l'intérieur est cliqué, rechargera toute la page par défaut :

Vous pouvez appelere.preventDefault()sur l'objet événement pour empêcher cela :

Ne confondez pase.stopPropagation()ete.preventDefault(). Ils sont tous deux utiles, mais ne sont pas liés :

  • e.stopPropagation()empêche les gestionnaires d'événements attachés aux balises supérieures de se déclencher.
  • e.preventDefault()empêche le comportement par défaut du navigateur pour les quelques événements qui en ont un.

Les gestionnaires d'événements peuvent-ils avoir des effets secondaires ?

Absolument ! Les gestionnaires d'événements sont l'endroit idéal pour les effets secondaires.

Contrairement aux fonctions de rendu, les gestionnaires d'événements n'ont pas besoin d'êtrepures, c'est donc un excellent endroit pourmodifierquelque chose—par exemple, changer la valeur d'une saisie en réponse à une frappe, ou modifier une liste en réponse à un appui sur un bouton. Cependant, pour modifier une information, vous devez d'abord disposer d'un moyen de la stocker. Dans React, cela se fait en utilisantl'état, la mémoire d'un composant.Vous en apprendrez davantage à ce sujet dans la page suivante.

Récapitulatif

  • Vous pouvez gérer les événements en passant une fonction comme prop à un élément tel que<button>.
  • Les gestionnaires d'événements doivent être passés,pas appelés !onClick={handleClick}, et nononClick={handleClick()}.
  • Vous pouvez définir une fonction de gestionnaire d'événements séparément ou en ligne.
  • Les gestionnaires d'événements sont définis à l'intérieur d'un composant, ils peuvent donc accéder aux props.
  • Vous pouvez déclarer un gestionnaire d'événements dans un parent et le passer comme prop à un enfant.
  • Vous pouvez définir vos propres props de gestionnaire d'événements avec des noms spécifiques à l'application.
  • Les événements se propagent vers le haut. Appeleze.stopPropagation()sur le premier argument pour empêcher cela.
  • Les événements peuvent avoir un comportement par défaut indésirable du navigateur. Appeleze.preventDefault()pour empêcher cela.
  • Appeler explicitement une prop de gestionnaire d'événements depuis un gestionnaire enfant est une bonne alternative à la propagation.

Essayez quelques défis

Challenge 1 of 2:Corriger un gestionnaire d'événement #

Cliquer sur ce bouton est censé basculer l'arrière-plan de la page entre le blanc et le noir. Cependant, rien ne se passe lorsque vous cliquez dessus. Corrigez le problème. (Ne vous inquiétez pas de la logique à l'intérieur de handleClick—cette partie est correcte.)