Contactez-nous

Passer des arguments aux gestionnaires d'événements

Découvrez différentes techniques pour passer des arguments supplémentaires (au-delà de l'objet événement) à vos fonctions gestionnaires d'événements en React.

Le besoin d'informations contextuelles

Nous savons maintenant comment définir un gestionnaire d'événements et comment il reçoit automatiquement l'objet événement synthétique (`event`). Cependant, il arrive souvent que le gestionnaire d'événements ait besoin d'informations supplémentaires spécifiques au contexte dans lequel l'événement s'est produit. Par exemple, si vous avez une liste d'éléments et que chaque élément a un bouton "Supprimer", le gestionnaire du clic doit savoir quel élément supprimer.

Comment pouvons-nous passer cet identifiant (ou toute autre donnée contextuelle) à notre fonction gestionnaire `handleDelete` lorsque l'utilisateur clique sur un bouton spécifique ? Nous ne pouvons pas simplement faire `onClick={handleDelete(itemId)}` car cela appellerait la fonction immédiatement lors du rendu, au lieu de passer une référence de fonction.

Heureusement, il existe plusieurs techniques courantes en React pour passer des arguments personnalisés aux gestionnaires d'événements au moment où l'événement est déclenché.

Méthode 1 : Fonctions fléchées en ligne

L'une des méthodes les plus simples et les plus courantes est d'utiliser une fonction fléchée directement dans l'attribut JSX de l'écouteur d'événements. Cette fonction fléchée en ligne ne fera qu'appeler votre véritable fonction gestionnaire en lui passant les arguments souhaités, ainsi que l'objet événement si nécessaire.

import React, { useState } from 'react';

function ListeProduits() {
  const [produits, setProduits] = useState([
    { id: 1, nom: 'Pomme' },
    { id: 2, nom: 'Banane' },
    { id: 3, nom: 'Orange' }
  ]);

  // Le gestionnaire reçoit maintenant l'ID en argument
  const handleSupprimerProduit = (idProduit) => {
    console.log('Suppression demandée pour ID :', idProduit);
    setProduits(produitsActuels => 
      produitsActuels.filter(p => p.id !== idProduit)
    );
  };

  return (
    
    {produits.map(produit => (
  • {produit.nom} {/* Fonction fléchée en ligne pour passer l'ID */}
  • ))}
); } export default ListeProduits;

Ici, pour chaque bouton "Supprimer", nous définissons une fonction fléchée `() => handleSupprimerProduit(produit.id)`. Lorsque le bouton est cliqué, c'est cette fonction fléchée qui est exécutée. Elle appelle alors notre fonction `handleSupprimerProduit` en lui passant l'identifiant `produit.id` spécifique à cet élément de la liste.

Si vous avez également besoin de l'objet événement dans `handleSupprimerProduit`, vous pouvez le passer explicitement depuis la fonction fléchée :

// Gestionnaire recevant l'événement et l'ID
const handleSupprimerProduitAvecEvent = (event, idProduit) => {
  event.stopPropagation(); // Exemple d'utilisation de l'event
  console.log('Suppression ID:', idProduit);
  // ... logique de suppression ...
};

// Utilisation dans le JSX

Méthode 2 : `Function.prototype.bind`

Une autre technique, moins courante aujourd'hui avec les fonctions fléchées mais parfois rencontrée dans du code plus ancien ou des composants classe, est d'utiliser la méthode `bind()` des fonctions JavaScript. `bind()` crée une nouvelle fonction dont la valeur `this` est définie et dont les premiers arguments sont pré-remplis.

En React, on peut l'utiliser pour pré-remplir des arguments pour un gestionnaire d'événements. Le premier argument de `bind` est la valeur de `this` (souvent `null` ou `this` dans une classe), suivi des arguments que vous voulez passer au gestionnaire.

// Le gestionnaire (supposons qu'il reçoive l'ID puis l'event)
const handleSupprimerAvecBind = (idProduit, event) => {
  console.log('ID via bind:', idProduit);
  console.log('Event:', event);
  // ... logique de suppression ...
};

// Utilisation dans le JSX

Ici, `handleSupprimerAvecBind.bind(null, produit.id)` crée une nouvelle fonction. Quand cette nouvelle fonction est appelée par React (lors du clic), elle appelle `handleSupprimerAvecBind` en lui passant d'abord l'argument pré-rempli (`produit.id`) puis l'objet événement synthétique fourni par React.

L'inconvénient de `bind` et des fonctions fléchées en ligne est qu'une nouvelle fonction est créée à chaque rendu, ce qui peut affecter les optimisations basées sur la comparaison de props (comme `React.memo` ou `shouldComponentUpdate`). Cependant, pour la plupart des cas, cet impact est négligeable.

Méthode 3 : Attributs `data-*` (Alternative moins directe)

Une approche différente consiste à ne pas passer l'argument directement via la fonction, mais à le stocker sur l'élément DOM lui-même en utilisant des attributs `data-*` et à le récupérer ensuite depuis l'objet `event` dans le gestionnaire.

// Gestionnaire unique qui lit l'attribut data-id
const handleSupprimerData = (event) => {
  // Récupère l'ID depuis l'attribut data-id du bouton cliqué
  const idProduit = event.target.dataset.id; 
  // Note: event.target.dataset.id retourne une chaîne, peut nécessiter parseInt()
  console.log('Suppression ID via data-*:', idProduit);
  // ... logique de suppression (convertir idProduit en nombre si nécessaire) ...
  setProduits(produitsActuels => 
    produitsActuels.filter(p => p.id !== parseInt(idProduit, 10))
  );
};

// Utilisation dans le JSX

Ici, chaque bouton a un attribut `data-id` contenant l'ID du produit. Le gestionnaire `handleSupprimerData` est le même pour tous les boutons. Quand un bouton est cliqué, le gestionnaire utilise `event.target.dataset.id` pour lire la valeur stockée dans l'attribut `data-id` de ce bouton spécifique.

Cette méthode évite de créer de nouvelles fonctions à chaque rendu, mais elle nécessite de manipuler le DOM (via `event.target`) pour récupérer l'information et implique souvent une conversion de type (les attributs `data-*` sont toujours des chaînes).

Choisir la bonne méthode

Pour la plupart des cas d'utilisation, l'utilisation de fonctions fléchées en ligne est la méthode la plus claire, la plus directe et la plus courante aujourd'hui en React pour passer des arguments personnalisés aux gestionnaires d'événements. Elle est facile à lire et à comprendre.

L'utilisation de `bind` est moins fréquente mais utile à connaître. L'approche avec les attributs `data-*` est une alternative viable, surtout si vous avez de très grandes listes et que vous êtes préoccupé par la création de nombreuses fonctions en ligne (bien que cela soit rarement un goulot d'étranglement réel).

Conclusion : Contextualiser les réactions

Passer des arguments spécifiques aux gestionnaires d'événements est essentiel pour que la logique de votre composant puisse réagir de manière contextuelle à l'interaction utilisateur (par exemple, savoir quel élément supprimer, quel article éditer, etc.). Les fonctions fléchées en ligne offrent la solution la plus simple et la plus lisible dans la majorité des cas, vous permettant d'invoquer votre gestionnaire principal avec les données précises dont il a besoin, en plus de l'objet événement fourni par React.