React onClick - przekazanie zdarzenia z parametrem


93

Bez parametru

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

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

Z parametrem

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

Chcę dostać event. Jak mogę to dostać?

Odpowiedzi:


166

Spróbuj tego:

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

A w twojej funkcji:

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

2
To spowodowało błąd eslint ( eslint.org/docs/rules/arrow-parens.html ) To, co zrobiłem, to zawijanie parametrów funkcji w nawiasyonClick={(e) => { this.clickMe(e, someparameter) }}
kretzm

1
Tak @kretzm Jeśli nie podajemy nawiasów klamrowych, działa to jako wyrażenie zwracające, gdy jest to pojedynczy wiersz, w przeciwnym razie musimy użyć nawiasów klamrowych, aby zawinąć jako treść funkcji.
Jyothi Babu Araja

4
Chcę tylko dodać, że nie jest to zalecana składnia. Z dokumentacji reactjs: Problem z tą składnią polega na tym, że przy każdym renderowaniu przycisku tworzone jest inne wywołanie zwrotne. W większości przypadków jest to w porządku. Jeśli jednak to wywołanie zwrotne zostanie przekazane jako właściwość do niższych komponentów, te komponenty mogą wykonać dodatkowe ponowne renderowanie. Ogólnie zalecamy wiązanie w konstruktorze lub używanie składni pól klas, aby uniknąć tego rodzaju problemów z wydajnością. Więcej informacji na stronie actjs.org
northernwind.

1
@Zwycięzca. Tak masz rację. Ale jeśli chcesz, aby kontekst twojego rodzica znajdował się w twoim wywołaniu zwrotnym, musisz mieć inne wywołanie zwrotne przy każdym renderowaniu. Właściwie to chyba kompromis.
Jyothi Babu Araja

@JyothiBabuAraja Myślę, że najlepszym rozwiązaniem jest wykorzystanie data-*atrybutów w HTML5. Zobacz moją odpowiedź poniżej, aby uzyskać więcej informacji.
Harry Chang

34

Dzięki ES6 możesz to zrobić w krótszy sposób:

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

I użyj go:

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

czy to również rozwiązuje problem tworzenia nowego wywołania zwrotnego? stackoverflow.com/questions/42597602/…
Otani Shuzo

1
oprócz tego możesz wysłać wiele parametrów. const clickMe = (parameter1, parameter2) => (event) => {// Zrób coś}
AhuraMazda,

1
Ten jest również uruchamiany po zamontowaniu komponentu, twój kod powinien wyglądać następująco:onClick={(e) => clickMe(someParameter)(e)}
Alexander Kim

Podobnie jak w przypadku kliknięcia Mnie, możesz również zniszczyć zdarzenie, nawet jeśli nie definiujesz go jako parametru.
Minh Kha

Dzięki za to. To działa. Ale dlaczego jest const clickMe = (parameter) => (event) => {...} zamiast tego const clickMe = (parameter) => {...}?
zrna

16

Rozwiązanie 1

function clickMe(parameter, event){
}

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

Rozwiązanie 2 Użycie funkcji bind jest uważane za lepsze niż sposób funkcji strzałkowej w rozwiązaniu 1. Należy zauważyć, że parametr zdarzenia powinien być ostatnim parametrem w funkcji obsługi

function clickMe(parameter, event){
}

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

+1 dla parametru zdarzenia będącego ostatnią rzeczą w rozwiązaniu nr 2. Wieki zajęło mi uświadomienie sobie, co robię źle, musiałem przegapić przyczynę gdzieś w dokumentach.
abelito

5

Aby całkowicie rozwiązać problem tworzenia nowego wywołania zwrotnego, użyj data-* atrybutów w HTML5 jest najlepszym rozwiązaniem IMO. Ponieważ w końcu, nawet jeśli wyodrębnisz komponent podrzędny, aby przekazać parametry, nadal tworzy on nowe funkcje.

Na przykład,

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

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

Zobacz https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes, aby dowiedzieć się, jak używać data-*atrybutów.


Podoba mi się to podejście. Proste i czyste
marknt15

5

Przykład curry z ES6:

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

Nasz przycisk, który przełącza obsługę:

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

Jeśli chcesz wywołać to wyrażenie funkcyjne bez obiektu zdarzenia, nazwałbyś to w ten sposób:

clickHandler(1)();

Ponadto, ponieważ reakcja wykorzystuje zdarzenia syntetyczne (opakowanie dla zdarzeń natywnych), istnieje pula zdarzeń , co oznacza, że ​​jeśli chcesz używać swojego eventobiektu asynchronicznie, musisz użyć 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.
};

Oto przykład na żywo: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark


Dlaczego nadal muszę mieć event.persist()z, console.log(event)ale nie potrzebuję tego z console.log(event.target)?
Isaac Pak


W tym kontekście szybsze jest użycie normalnej funkcji otrzymującej 2 parametry niż curry. możesz uruchomić test porównawczy w jsben.ch
ncesar

@imentsar Jak skonfigurować Reacta w jsben.ch? Opublikuj swój plz testowy.
Isaac Pak

@IsaacPak jsben to proste narzędzie do testowania kodów javascript. W zasadzie umieszczasz dwie różne próbki kodu i porównujesz ich szybkość. Nie musisz umieszczać całego kodu Reacta, wystarczy funkcja, która Twoim zdaniem może być wolniejsza i którą chcesz przetestować. Ponadto zawsze używam jsben.ch i jsbench.me, aby się upewnić. W kontekście clickHandler trzeba by mockować niektóre kody. W ten let event;sposób nie spowoduje to nieokreślonego błędu.
ncesar
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.