React onClick - passer l'événement avec le paramètre

93

Sans paramètre

function clickMe(e){
  //e is the event
}

<button onClick={this.clickMe}></button>

Avec paramètre

function clickMe(parameter){
  //how to get the "e" ?
}
<button onClick={() => this.clickMe(someparameter)}></button>

Je veux obtenir le fichier event. Comment puis-je l'avoir?

IMOBAMA
la source

Réponses:

166

Essaye ça:

<button onClick={(e) => {
     this.clickMe(e, someParameter)
}}>Click Me!</button>

Et dans votre fonction:

function clickMe(event, someParameter){
     //do with event
}
Jyothi Babu Araja
la source
2
Cela m'avait donné une erreur eslint ( eslint.org/docs/rules/arrow-parens.html ) Ce que j'ai fait, c'est mettre les paramètres de fonction entre parenthèsesonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm
1
Oui @kretzm Si nous ne donnons pas d'accolades, cela agit comme une expression de retour lorsqu'il s'agit d'une seule ligne sinon nous devons utiliser des accolades pour envelopper comme corps de fonction.
Jyothi Babu Araja
4
Je veux juste ajouter que ce n'est pas une syntaxe recommandée. À partir de la documentation reactjs: Le problème avec cette syntaxe est qu'un rappel différent est créé à chaque fois que le bouton est rendu. Dans la plupart des cas, c'est bien. Cependant, si ce rappel est passé comme accessoire aux composants inférieurs, ces composants peuvent effectuer un nouveau rendu supplémentaire. Nous recommandons généralement la liaison dans le constructeur ou l'utilisation de la syntaxe des champs de classe, pour éviter ce genre de problème de performances. Plus d'infos sur reactjs.org
Northernwind
1
@Victor. Oui, tu as raison. Mais si vous voulez le contexte de votre parent dans votre rappel, vous devez avoir un rappel différent sur chaque rendu. En fait, c'est un compromis, je pense.
Jyothi Babu Araja
@JyothiBabuAraja Je pense que la meilleure solution est d'utiliser les data-*attributs en HTML5. Veuillez consulter ma réponse ci-dessous pour plus de détails.
Harry Chang
34

Avec l'ES6, vous pouvez faire de manière plus courte comme ceci:

const clickMe = (parameter) => (event) => {
    // Do something
}

Et utilisez-le:

<button onClick={clickMe(someParameter)} />
Minh Kha
la source
cela résout-il également la création d'un nouveau problème de rappel? stackoverflow.com/questions/42597602/…
Otani Shuzo
1
en plus de cela, vous pouvez envoyer plusieurs paramètres. const clickMe = (parameter1, parameter2) => (event) => {// Faire quelque chose}
AhuraMazda
1
Celui-ci est également déclenché lorsque votre composant est monté, votre code doit être:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim
De la même manière que si vous cliquez simplement sur Moi, vous pouvez également détruire l'événement, même si vous ne le définissez pas comme paramètre.
Minh Kha le
Merci pour cela. Ça marche. Mais pourquoi existe-t-il à la const clickMe = (parameter) => (event) => {...} place const clickMe = (parameter) => {...}?
zrna
16

Solution 1

function clickMe(parameter, event){
}

<button onClick={(event) => {this.clickMe(someparameter, event)}></button>

Solution 2 L' utilisation de la fonction de liaison est considérée comme meilleure que celle de la fonction flèche dans la solution 1. Notez que le paramètre d'événement doit être le dernier paramètre de la fonction de gestionnaire

function clickMe(parameter, event){
}

<button onClick={this.clickMe.bind(this, someParameter)}></button>
Bence Dergez
la source
+1 pour le paramètre d'événement étant la dernière chose de la solution n ° 2. Il m'a fallu une éternité pour réaliser ce que je faisais mal, j'ai dû manquer la raison quelque part dans la documentation.
abelito
5

Pour résoudre complètement le problème de création de nouveaux rappels, utiliser les data-*attributs en HTML5 est la meilleure solution IMO. Car en fin de compte, même si vous extrayez un sous-composant pour passer les paramètres, cela crée quand même de nouvelles fonctions.

Par exemple,

const handleBtnClick = e => {
  const { id } = JSON.parse(e.target.dataset.onclickparam);
  // ...
};

<button onClick={handleBtnClick} data-onclickparam={JSON.stringify({ id: 0 })}>

Voir https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes pour l'utilisation des data-*attributs.

Harry Chang
la source
J'aime cette approche. Simple et propre
marknt15
5

Exemple de curry avec ES6:

const clickHandler = param => event => {
  console.log(param); // your parameter
  console.log(event.type); // event type, e.g.: click, etc.
};

Notre bouton, qui bascule le gestionnaire:

<button onClick={(e) => clickHandler(1)(e)}>Click me!</button>

Si vous souhaitez appeler cette expression de fonction sans objet d'événement, vous l'appelez ainsi:

clickHandler(1)();

De plus, étant donné que react utilise des événements synthétiques (un wrapper pour les événements natifs), il existe un élément de regroupement d'événements , ce qui signifie que si vous souhaitez utiliser votre eventobjet de manière asynchrone, vous devez utiliser event.persist():

const clickHandler = param => event => {
  event.persist();
  console.log(event.target);
  setTimeout(() => console.log(event.target), 1000); // won't be null, otherwise if you haven't used event.persist() it would be null.
};

Voici un exemple en direct: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark

Alexandre Kim
la source
Pourquoi ai-je encore besoin d'avoir event.persist()avec console.log(event)mais je n'en ai pas besoin avec console.log(event.target)?
Isaac Pak le
1
Lisez ceci: reactjs.org/docs/events.html#event- Covoiturage
Alexander Kim le
Dans ce contexte, il est plus rapide d'utiliser une fonction normale recevant 2 paramètres que le currying. vous pouvez exécuter un test de référence dans jsben.ch
ncesar
@ncesar Comment configurez-vous React dans jsben.ch? Postez votre test plz.
Isaac Pak le
@IsaacPak jsben est un outil simple pour tester les codes javascript. Vous placez à peu près deux échantillons de code différents et comparez leur vitesse. Vous n'avez pas besoin de mettre tout votre code React, juste une fonction que vous pensez être plus lente et que vous souhaitez tester. De plus, j'utilise toujours jsben.ch et jsbench.me juste pour m'en assurer. Dans le contexte clickHandler, vous devez simuler certains codes. Ainsi let event;, il ne lancera pas une erreur non définie.
ncesar le