React onClick - pasar evento con parámetro

93

Sin parámetro

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

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

Con parámetro

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

Quiero conseguir el event. ¿Cómo puedo obtenerlo?

IMOBAMA
fuente

Respuestas:

166

Prueba esto:

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

Y en tu función:

function clickMe(event, someParameter){
     //do with event
}
Jyothi Babu Araja
fuente
2
Esto me había dado un error de eslint ( eslint.org/docs/rules/arrow-parens.html ) Lo que hice fue ajustar los parámetros de la función entre paréntesisonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm
1
Sí @kretzm Si no damos llaves, actúa como una expresión de retorno cuando es una sola línea; de lo contrario, debemos usar llaves para ajustar como un cuerpo de función.
Jyothi Babu Araja
4
Solo quiero agregar que es una sintaxis no recomendada. De los documentos de reactjs: El problema con esta sintaxis es que se crea una devolución de llamada diferente cada vez que se procesa el botón. En la mayoría de los casos, esto está bien. Sin embargo, si esta devolución de llamada se pasa como un apoyo a los componentes inferiores, esos componentes podrían realizar una nueva representación adicional. Por lo general, recomendamos enlazar en el constructor o usar la sintaxis de los campos de clase para evitar este tipo de problema de rendimiento. Más información en reactjs.org
northernwind
1
@Víctor. Sí, tiene usted razón. Pero si desea el contexto de su padre dentro de su devolución de llamada, debe tener una devolución de llamada diferente en cada render. En realidad, creo que es una compensación.
Jyothi Babu Araja
@JyothiBabuAraja Creo que la mejor solución es utilizar los data-*atributos en HTML5. Consulte mi respuesta a continuación para obtener más detalles.
Harry Chang
34

Con el ES6, puede hacer de una manera más corta como esta:

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

Y úsalo:

<button onClick={clickMe(someParameter)} />
Minh Kha
fuente
¿Esto también resuelve la creación de un nuevo problema de devolución de llamada? stackoverflow.com/questions/42597602/…
Otani Shuzo
1
Además de esto, puede enviar múltiples parámetros. const clickMe = (parameter1, parameter2) => (event) => {// Do something}
AhuraMazda
1
Este también se activa cuando se monta su componente, su código debe ser:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim
De manera similar a si solo hace clic en mí, también puede destruir el evento, incluso si no lo define como un parámetro.
Minh Kha
Gracias por esto. Funciona. Pero, ¿por qué hay en su const clickMe = (parameter) => (event) => {...} lugar const clickMe = (parameter) => {...}?
zrna
16

Solución 1

function clickMe(parameter, event){
}

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

Solución 2 El uso de la función de vinculación se considera mejor, que la forma de la función de flecha, en la solución 1. Tenga en cuenta que el parámetro de evento debe ser el último parámetro en la función de controlador

function clickMe(parameter, event){
}

<button onClick={this.clickMe.bind(this, someParameter)}></button>
Bence Dergez
fuente
+1 para que el parámetro de evento sea lo último en la solución n. ° 2. Me tomó una eternidad darme cuenta de lo que estaba haciendo mal, debí haber perdido la razón en algún lugar de los documentos.
abelito
5

Para resolver completamente el problema de creación de una nueva devolución de llamada, utilizar los data-*atributos en HTML5 es la mejor solución en mi opinión. Dado que al final del día, incluso si extrae un subcomponente para pasar los parámetros, aún crea nuevas funciones.

Por ejemplo,

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

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

Consulte https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes para usar data-*atributos.

Harry Chang
fuente
Me gusta este enfoque. Simple y limpio
marknt15
5

Ejemplo de curry con ES6:

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

Nuestro botón, que cambia el controlador:

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

Si desea llamar a esta expresión de función sin un objeto de evento, la llamaría de esta manera:

clickHandler(1)();

Además, dado que react usa eventos sintéticos (una envoltura para eventos nativos), hay una agrupación de eventos , lo que significa que, si desea usar su eventobjeto de forma asincrónica, entonces tendrá que usar 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.
};

Aquí hay un ejemplo en vivo: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark

Alexander Kim
fuente
¿Por qué todavía necesito tener event.persist()con console.log(event)pero no lo necesito con console.log(event.target)?
Isaac Pak
1
Lea esto: reactjs.org/docs/events.html#event-pooling
Alexander Kim
En este contexto, es más rápido utilizar una función normal recibiendo 2 parámetros que curando. puede ejecutar una prueba de referencia en jsben.ch
ncesar
@ncesar ¿Cómo se configura React en jsben.ch? Publique su prueba por favor.
Isaac Pak
@IsaacPak jsben es una herramienta simple para probar códigos javascript. Prácticamente colocas dos muestras diferentes de código y comparas su velocidad. No tienes que poner todo tu código de React, solo una función que crees que puede ser más lenta y quieres probar. Además, siempre uso jsben.ch y jsbench.me solo para asegurarme. En el contexto de clickHandler, necesitaría simular algunos códigos. Así let event;no arrojará un error indefinido.
ncesar