React onClick - truyền sự kiện với tham số


93

Không có tham số

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

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

Có tham số

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

Tôi muốn lấy event. Làm thế nào tôi có thể nhận được nó?

Câu trả lời:


170

Thử đi:

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

Và trong chức năng của bạn:

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

2
Điều này đã cho tôi một lỗi eslint ( eslint.org/docs/rules/arrow-parens.html ) Những gì tôi đã làm là quấn thông số chức năng trong ngoặc đơnonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm

1
Có @kretzm Nếu chúng ta không cung cấp dấu ngoặc nhọn, nó hoạt động như một biểu thức trả về khi nó là một dòng đơn lẻ khác, chúng ta phải sử dụng dấu ngoặc nhọn để bao bọc như một thân hàm.
Jyothi Babu Araja

4
Tôi chỉ muốn nói thêm rằng đó là một cú pháp không được khuyến nghị. Từ tài liệu reactjs: Vấn đề với cú pháp này là một lệnh gọi lại khác được tạo mỗi khi nút hiển thị. Trong hầu hết các trường hợp, điều này là tốt. Tuy nhiên, nếu lệnh gọi lại này được chuyển như một chỗ dựa cho các thành phần thấp hơn, thì những thành phần đó có thể thực hiện một kết xuất bổ sung. Thông thường, chúng tôi khuyên bạn nên liên kết trong hàm tạo hoặc sử dụng cú pháp các trường lớp, để tránh loại vấn đề hiệu suất này. Xem thêm thông tin tại reactjs.org
northernwind

1
@Victor. Có bạn đúng. Nhưng nếu bạn muốn ngữ cảnh của cha mẹ bên trong lệnh gọi lại của mình, bạn cần có các lệnh gọi lại khác nhau trên mỗi lần hiển thị. Thực ra đó là một sự đánh đổi tôi nghĩ.
Jyothi Babu Araja

@JyothiBabuAraja Tôi nghĩ giải pháp tốt nhất là sử dụng các data-*thuộc tính trong HTML5. Hãy xem câu trả lời của tôi dưới đây để biết thêm chi tiết.
Harry Chang

34

Với ES6, bạn có thể làm theo cách ngắn hơn như sau:

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

Và sử dụng nó:

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

điều này có giải quyết được vấn đề gọi lại mới không? stackoverflow.com/questions/42597602/…
Otani Shuzo

1
ngoài điều này, bạn có thể gửi nhiều tham số. const clickMe = (tham số1, tham số2) => (sự kiện) => {// Làm điều gì đó}
AhuraMazda

1
Cái này cũng được kích hoạt khi thành phần của bạn được gắn kết, mã của bạn phải là:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim

Tương tự như nếu chỉ clickMe, bạn cũng có thể hủy sự kiện, ngay cả khi bạn không xác định nó như một tham số.
Minh Kha

Cám ơn vì cái này. Nó hoạt động. Nhưng tại sao lại có const clickMe = (parameter) => (event) => {...} thay const clickMe = (parameter) => {...}?
zrna

16

Giải pháp 1

function clickMe(parameter, event){
}

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

Giải pháp 2 Sử dụng hàm liên kết được coi là tốt hơn, so với cách hàm mũi tên, trong giải pháp 1. Lưu ý rằng tham số sự kiện phải là tham số cuối cùng trong hàm xử lý

function clickMe(parameter, event){
}

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

+1 cho tham số sự kiện là điều cuối cùng trong giải pháp số 2. Khiến tôi mãi mãi mới nhận ra mình đã làm gì sai, hẳn là tôi đã bỏ sót lý do ở đâu đó trong tài liệu.
abelito

5

Để giải quyết triệt để vấn đề tạo lệnh gọi lại mới, sử dụng các data-*thuộc tính trong HTML5 là giải pháp tốt nhất IMO. Vì cuối cùng, ngay cả khi bạn trích xuất một thành phần phụ để chuyển các tham số, nó vẫn tạo ra các chức năng mới.

Ví dụ,

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

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

Xem https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes để sử dụng data-*thuộc tính.


Tôi thích cách tiếp cận này. Đơn giản và sạch sẽ
marknt15

5

Tách lạng bộ với ES6 dụ:

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

Nút của chúng tôi, trình xử lý bật tắt:

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

Nếu bạn muốn gọi biểu thức hàm này mà không có đối tượng sự kiện, thì bạn sẽ gọi nó theo cách này:

clickHandler(1)();

Ngoài ra, vì react sử dụng các sự kiện tổng hợp (một trình bao bọc cho các sự kiện gốc), nên có một điều là gộp sự kiện , có nghĩa là, nếu bạn muốn sử dụng eventđối tượng của mình một cách không đồng bộ, thì bạn phải sử dụng 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.
};

Đây là ví dụ trực tiếp: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark


Tại sao tôi vẫn cần phải có event.persist()với console.log(event)nhưng tôi không cần nó với console.log(event.target)?
Isaac Pak


Trong bối cảnh này, việc sử dụng một hàm bình thường nhận 2 tham số sẽ nhanh hơn so với việc sử dụng hàm currying. bạn có thể chạy kiểm tra điểm chuẩn trong jsben.ch
ncesar

@ncesar Làm cách nào để bạn thiết lập React trong jsben.ch? Làm ơn gửi bài kiểm tra của bạn.
Isaac Pak

@IsaacPak jsben là một công cụ đơn giản để kiểm tra mã javascript. Bạn có thể đặt hai mẫu mã khác nhau và so sánh tốc độ của chúng. Bạn không phải đặt toàn bộ mã React của mình, chỉ cần một chức năng mà bạn nghĩ có thể chậm hơn và bạn muốn thử nghiệm. Ngoài ra, tôi luôn sử dụng jsben.ch và jsbench.me chỉ để đảm bảo. Trong ngữ cảnh clickHandler, bạn sẽ cần phải mô phỏng một số mã. Giống như let event;vậy nó sẽ không tạo ra một lỗi không xác định.
ncesar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.