React onClick - evento de passagem com parâmetro


99

Sem Parâmetro

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

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

Com Parâmetro

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

Eu quero pegar o event. Como posso conseguir?

Respostas:


178

Experimente isto:

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

E em sua função:

function clickMe(event, someParameter){
     //do with event
}

3
Isso me deu um erro eslint ( eslint.org/docs/rules/arrow-parens.html ) O que fiz foi colocar os parâmetros da função entre parêntesesonClick={(e) => { this.clickMe(e, someparameter) }}
— kretzm

1
Sim @kretzm Se não fornecermos colchetes, ele atua como uma expressão de retorno quando for uma única linha, caso contrário, devemos usar colchetes para quebrar como um corpo de função.
— Jyothi Babu Araja

4
Só quero acrescentar que não é uma sintaxe recomendada. Dos documentos reactjs: O problema com essa sintaxe é que um retorno de chamada diferente é criado cada vez que o botão é renderizado. Na maioria dos casos, isso é bom. No entanto, se esse retorno de chamada for passado como um suporte para componentes inferiores, esses componentes podem fazer uma nova renderização extra. Geralmente recomendamos vincular no construtor ou usar a sintaxe dos campos de classe, para evitar esse tipo de problema de desempenho. Mais informações em reactjs.org
— northernwind

1
@Vencedor. Sim você está certo. Mas se você quiser o contexto do seu pai dentro do seu retorno de chamada, você precisa ter um retorno de chamada diferente em cada renderização. Na verdade, é uma troca, eu acho.
— Jyothi Babu Araja

@JyothiBabuAraja Acho que a melhor solução é utilizar os data-*atributos em HTML5. Por favor, veja minha resposta abaixo para mais detalhes.
— Harry Chang de

38

Com o ES6, você pode fazer de forma mais curta, como este:

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

E use-o:

<button onClick={clickMe(someParameter)} />

isso também resolve a criação de um novo problema de retorno de chamada? stackoverflow.com/questions/42597602/…
— Otani Shuzo

1
além disso, você pode enviar vários parâmetros. const clickMe = (parâmetro1, parâmetro2) => (evento) => {// Faça algo}
— AhuraMazda

1
Este também é disparado quando seu componente é montado, seu código deve ser:onClick={(e) => clickMe(someParameter)(e)}
— Alexander Kim

Da mesma forma que se apenas clickMe, você também pode destruir o evento, mesmo que você não o defina como um parâmetro.
— Minh Kha

Obrigado por isso. Funciona. Mas por que há const clickMe = (parameter) => (event) => {...} em vez const clickMe = (parameter) => {...}?
— zrna,

17

Solução 1

function clickMe(parameter, event){
}

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

Solução 2 O uso da função de vinculação é considerado melhor do que o método da função de seta, na solução 1. Observe que o parâmetro do evento deve ser o último parâmetro na função do manipulador

function clickMe(parameter, event){
}

<button onClick={this.clickMe.bind(this, someParameter)}></button>

1 para o parâmetro de evento sendo a última coisa na solução # 2. Levei uma eternidade para perceber o que estava fazendo de errado, devo ter perdido o motivo em algum lugar dos documentos.
— abelito de

5

Para resolver completamente o problema de criação de um novo retorno de chamada, utilizar os data-*atributos em HTML5 é a melhor solução IMO. Pois no final do dia, mesmo que você extraia um subcomponente para passar os parâmetros, ele ainda cria novas funções.

Por exemplo,

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 os data-*atributos.


Eu gosto dessa abordagem. Simples e limpo
— marknt15

5

Currying com ES6 exemplo:

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

Nosso botão, que alterna o manipulador:

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

Se você quiser chamar esta expressão de função sem um objeto de evento, chame-a desta forma:

clickHandler(1)();

Além disso, como o react usa eventos sintéticos (um wrapper para eventos nativos), existe um pool de eventos , o que significa que, se você quiser usar seu eventobjeto de forma assíncrona, terá 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.
};

Aqui está um exemplo ao vivo: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark


Por que ainda preciso ter event.persist()com, console.log(event)mas não preciso com console.log(event.target)?
— Isaac Pak


Neste contexto, é mais rápido usar uma função normal recebendo 2 parâmetros do que currying. você pode executar um teste de benchmark em jsben.ch
— ncesar de

@ncesar Como você configura o React em jsben.ch? Publique seu teste, plz.
— Isaac Pak

@IsaacPak jsben é uma ferramenta simples para testar códigos javascript. Você basicamente coloca dois exemplos diferentes de código e compara sua velocidade. Você não precisa colocar todo o código React, apenas uma função que você acha que pode ser mais lenta e deseja testar. Além disso, sempre uso jsben.ch e jsbench.me apenas para ter certeza. No contexto clickHandler, você precisaria simular alguns códigos. Assim let event;, não vai gerar um erro indefinido.
— ncesar de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.