ตอบสนอง onClick - ส่งผ่านเหตุการณ์ด้วยพารามิเตอร์


93

ไม่มีพารามิเตอร์

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

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

ด้วยพารามิเตอร์

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

ฉันต้องการรับไฟล์event. ฉันจะรับมันได้อย่างไร?

คำตอบ:


168

ลองสิ่งนี้:

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

และในฟังก์ชันของคุณ:

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

2
สิ่งนี้ทำให้ฉันมีข้อผิดพลาด eslint ( eslint.org/docs/rules/arrow-parens.html ) สิ่งที่ฉันทำคือห่อพารามิเตอร์ฟังก์ชันไว้ในวงเล็บonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm

1
ใช่ @kretzm ถ้าเราไม่จัดฟันมันจะทำหน้าที่เป็นนิพจน์ส่งกลับเมื่อมันเป็นบรรทัดเดียวอื่น ๆ เราต้องใช้วงเล็บปีกกาเพื่อห่อเป็นส่วนที่ใช้งานได้
Jyothi Babu Araja

4
ฉันแค่อยากจะเพิ่มว่ามันเป็นไวยากรณ์ที่ไม่แนะนำ จากเอกสาร reactjs: ปัญหาเกี่ยวกับไวยากรณ์นี้คือการเรียกกลับที่แตกต่างกันถูกสร้างขึ้นทุกครั้งที่ปุ่มแสดงผล ในกรณีส่วนใหญ่ก็ใช้ได้ อย่างไรก็ตามหากการเรียกกลับนี้ถูกส่งผ่านไปยังส่วนประกอบที่ต่ำกว่าส่วนประกอบเหล่านั้นอาจทำการเรนเดอร์เพิ่มเติม โดยทั่วไปเราแนะนำให้ผูกในตัวสร้างหรือใช้ไวยากรณ์ของฟิลด์คลาสเพื่อหลีกเลี่ยงปัญหาประสิทธิภาพการทำงานประเภทนี้ ข้อมูลเพิ่มเติมได้ที่reactjs.org
northernwind

1
@ วิกเตอร์. ใช่คุณถูก. แต่ถ้าคุณต้องการให้บริบทของผู้ปกครองอยู่ในการโทรกลับคุณจะต้องมีการเรียกกลับที่แตกต่างกันในการแสดงผลแต่ละครั้ง จริงๆแล้วมันเป็นการแลกเปลี่ยนฉันคิดว่า
Jyothi Babu Araja

@JyothiBabuAraja ฉันคิดว่าทางออกที่ดีที่สุดคือใช้data-*แอตทริบิวต์ใน HTML5 โปรดดูคำตอบของฉันด้านล่างสำหรับรายละเอียดเพิ่มเติม
Harry Chang

34

ด้วย ES6 คุณสามารถทำได้สั้นกว่านี้:

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

และใช้มัน:

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

สิ่งนี้ยังช่วยแก้ปัญหาการสร้างการโทรกลับใหม่ได้หรือไม่ stackoverflow.com/questions/42597602/…
Otani Shuzo

1
นอกจากนี้คุณสามารถส่งพารามิเตอร์ได้หลายตัว const clickMe = (parameter1, parameter2) => (event) => {// Do something}
AhuraMazda

1
อันนี้จะเริ่มทำงานเมื่อส่วนประกอบของคุณติดตั้งรหัสของคุณควรเป็น:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim

เช่นเดียวกับถ้าเพียงแค่ clickMe คุณยังสามารถทำลายเหตุการณ์ได้แม้ว่าคุณจะไม่ได้กำหนดเป็นพารามิเตอร์ก็ตาม
มินคา

ขอบคุณสำหรับสิ่งนี้. มันได้ผล. แต่ทำไมมีconst clickMe = (parameter) => (event) => {...} แทนconst clickMe = (parameter) => {...}?
zrna

16

โซลูชันที่ 1

function clickMe(parameter, event){
}

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

โซลูชันที่ 2 การใช้ฟังก์ชันการผูกถือว่าดีกว่าฟังก์ชันลูกศรในโซลูชัน 1 โปรดทราบว่าพารามิเตอร์เหตุการณ์ควรเป็นพารามิเตอร์สุดท้ายในฟังก์ชันตัวจัดการ

function clickMe(parameter, event){
}

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

+1 สำหรับพารามิเตอร์เหตุการณ์เป็นสิ่งสุดท้ายในโซลูชัน # 2 พาฉันไปตลอดเพื่อตระหนักว่าฉันทำอะไรผิดฉันคงพลาดเหตุผลบางอย่างในเอกสาร
abelito

5

เพื่อแก้ปัญหาการสร้างการโทรกลับใหม่โดยสมบูรณ์ให้ใช้data-*แอตทริบิวต์ใน HTML5 ซึ่งเป็นทางออกที่ดีที่สุดของ IMO เนื่องจากในตอนท้ายของวันแม้ว่าคุณจะแยกองค์ประกอบย่อยเพื่อส่งผ่านพารามิเตอร์ แต่ก็ยังคงสร้างฟังก์ชันใหม่

ตัวอย่างเช่น,

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

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

ดูhttps://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributesสำหรับการใช้data-*แอตทริบิวต์


ฉันชอบแนวทางนี้ เรียบง่ายและสะอาด
marknt15

5

แกงด้วย ES6 ตัวอย่าง:

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

ปุ่มของเราที่สลับตัวจัดการ:

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

หากคุณต้องการเรียกใช้นิพจน์ฟังก์ชันนี้โดยไม่มีอ็อบเจ็กต์เหตุการณ์คุณจะเรียกมันด้วยวิธีนี้:

clickHandler(1)();

นอกจากนี้เนื่องจาก react ใช้เหตุการณ์สังเคราะห์ (wrapper สำหรับเหตุการณ์เนทีฟ) จึงมีเหตุการณ์รวมกันซึ่งหมายความว่าหากคุณต้องการใช้eventออบเจ็กต์แบบอะซิงโครนัสคุณจะต้องใช้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.
};

นี่คือตัวอย่างสด: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark


ทำไมฉันยังคงต้องมีevent.persist()ด้วยconsole.log(event)แต่ผมไม่จำเป็นต้องมีconsole.log(event.target)?
Isaac Pak

1
อ่านสิ่งนี้: reactjs.org/docs/events.html#event-pooling
Alexander Kim

ในบริบทนี้การใช้ฟังก์ชันปกติที่ได้รับ 2 params จะเร็วกว่าการแกง คุณสามารถเรียกใช้การทดสอบเกณฑ์มาตรฐานใน jsben.ch
ncesar

@ncesar คุณตั้งค่า React ใน jsben.ch ได้อย่างไร? โพสต์การทดสอบของคุณกรุณา
Isaac Pak

@IsaacPak jsben เป็นเครื่องมือง่ายๆในการทดสอบรหัสจาวาสคริปต์ คุณวางตัวอย่างโค้ดสองตัวอย่างที่แตกต่างกันและเปรียบเทียบความเร็ว คุณไม่จำเป็นต้องใส่รหัส React ทั้งหมดของคุณเพียงแค่ฟังก์ชันที่คุณคิดว่าอาจทำงานช้าลงและคุณต้องการทดสอบ นอกจากนี้ฉันมักจะใช้ jsben.ch และ jsbench.me เพื่อให้แน่ใจ ในบริบท clickHandler คุณจะต้องจำลองโค้ดบางอย่าง ชอบlet event;จึงเคยชินโยนข้อผิดพลาดที่ไม่ได้กำหนด
ncesar
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.