React onClick - lewati event dengan parameter


93

Tanpa Parameter

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

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

Dengan Parameter

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

Saya ingin mendapatkan event. Bagaimana saya mendapatkannya?

Jawaban:


167

Coba ini:

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

Dan dalam fungsi Anda:

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

2
Ini telah memberi saya kesalahan eslint ( eslint.org/docs/rules/arrow-parens.html ) Apa yang saya lakukan adalah membungkus parameter fungsi dalam tanda kurungonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm

1
Ya @kretzm Jika kita tidak memberikan tanda kurung, ini bertindak sebagai ekspresi kembali ketika itu satu baris, jika tidak kita harus menggunakan tanda kurung untuk membungkus sebagai badan fungsi.
Jyothi Babu Araja

4
Saya hanya ingin menambahkan bahwa ini adalah sintaks yang tidak direkomendasikan. Dari dokumen reactjs: Masalah dengan sintaks ini adalah bahwa panggilan balik yang berbeda dibuat setiap kali tombol dirender. Dalam kebanyakan kasus, ini bagus. Namun, jika callback ini diteruskan sebagai prop ke komponen yang lebih rendah, komponen tersebut mungkin melakukan rendering ulang ekstra. Kami biasanya merekomendasikan mengikat dalam konstruktor atau menggunakan sintaks bidang kelas, untuk menghindari masalah kinerja semacam ini. Info lebih lanjut di reactjs.org
northernwind

1
@Pemenang. Ya kamu benar. Tetapi jika Anda ingin konteks orang tua Anda di dalam callback, Anda perlu memiliki callback yang berbeda pada setiap render. Sebenarnya itu adalah pertukaran, saya pikir.
Jyothi Babu Araja

@JyothiBabuAraja Saya pikir solusi terbaik adalah dengan memanfaatkan data-*atribut di HTML5. Silakan lihat jawaban saya di bawah ini untuk lebih jelasnya.
Harry Chang

34

Dengan ES6, Anda dapat melakukannya dengan cara yang lebih singkat seperti ini:

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

Dan gunakan itu:

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

apakah ini juga menyelesaikan masalah pembuatan panggilan balik baru? stackoverflow.com/questions/42597602/…
Otani Shuzo

1
selain itu, Anda dapat mengirim beberapa parameter. const clickMe = (parameter1, parameter2) => (event) => {// Lakukan sesuatu}
AhuraMazda

1
Yang ini juga diaktifkan ketika komponen Anda dipasang, kode Anda harus:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim

Sama halnya jika hanya clickMe, Anda juga dapat merusak acara, bahkan jika Anda tidak mendefinisikannya sebagai parameter.
Minh Kha

Terima kasih untuk ini. Berhasil. Tapi kenapa const clickMe = (parameter) => (event) => {...} malah ada const clickMe = (parameter) => {...}?
zrna

16

Solusi 1

function clickMe(parameter, event){
}

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

Solusi 2 Menggunakan fungsi mengikat dianggap lebih baik, daripada cara fungsi panah, dalam solusi 1. Perhatikan, bahwa parameter peristiwa harus menjadi parameter terakhir dalam fungsi handler

function clickMe(parameter, event){
}

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

+1 untuk parameter peristiwa menjadi hal terakhir dalam solusi # 2. Butuh waktu lama bagi saya untuk menyadari apa yang saya lakukan salah, saya pasti melewatkan alasannya di suatu tempat di dokumen.
abelito

5

Untuk mengatasi masalah pembuatan panggilan balik baru sepenuhnya, memanfaatkan data-*atribut dalam HTML5 adalah solusi terbaik IMO. Karena pada akhirnya, meskipun Anda mengekstrak sub-komponen untuk meneruskan parameter, itu masih membuat fungsi baru.

Sebagai contoh,

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

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

Lihat https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes untuk menggunakan data-*atribut.


Saya suka pendekatan ini. Sederhana dan bersih
marknt15

5

Currying dengan ES6 contoh:

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

Tombol kami, yang mengalihkan penangan:

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

Jika Anda ingin memanggil ekspresi fungsi ini tanpa objek event, maka Anda akan memanggilnya seperti ini:

clickHandler(1)();

Selain itu, karena react menggunakan kejadian sintetis (pembungkus untuk kejadian asli), ada hal penggabungan kejadian , yang berarti, jika Anda ingin menggunakan eventobjek secara asinkron, Anda harus menggunakan 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.
};

Berikut contoh langsungnya: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark


Mengapa saya masih perlu event.persist()dengan console.log(event)tetapi saya tidak membutuhkannya console.log(event.target)?
Isaac Pak


Dalam konteks ini, lebih cepat menggunakan fungsi normal yang menerima 2 parameter daripada kari. Anda dapat menjalankan tes benchmark di jsben.ch
ncesar

@ncesar Bagaimana Anda mengatur React di jsben.ch? Posting tes Anda, tolong.
Isaac Pak

@IsaacPak jsben adalah alat sederhana untuk menguji kode javascript. Anda cukup banyak menempatkan dua contoh kode yang berbeda dan membandingkan kecepatannya. Anda tidak perlu memasukkan seluruh kode React Anda, cukup fungsi yang menurut Anda mungkin lebih lambat dan ingin Anda uji. Juga, saya selalu menggunakan jsben.ch dan jsbench.me hanya untuk memastikan. Dalam konteks clickHandler, Anda perlu memalsukan beberapa kode. Seperti let event;itu tidak akan menimbulkan kesalahan yang tidak ditentukan.
ncesar
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.