171

Without Parameter

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

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

With Parameter

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

I want to get the event. How can I get it?

5 Answers 5

293

Try this:

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

And in your function:

function clickMe(event, someParameter){
     //do with event
}
Sign up to request clarification or add additional context in comments.

6 Comments

This had given me an eslint error (eslint.org/docs/rules/arrow-parens.html) What I did was wrap the function parameters in parentheses onClick={(e) => { this.clickMe(e, someparameter) }}
Yes @kretzm If we don't give braces, it acts as a return expression when it's single line else we must use braces to wrap as a function body.
I just want to add that it's a not recommended syntax. From the reactjs docs: The problem with this syntax is that a different callback is created each time the button renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem. More info at reactjs.org
@Victor. Yes you are right. But if you want the context of your parent inside your callback, you need to have different callback on each render. Actually it's a trade off I think.
@JyothiBabuAraja I think the best solution is to utilize the data-* attributes in HTML5. Please see my answer below for more details.
|
73

With the ES6, you can do in a shorter way like this:

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

And use it:

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

9 Comments

does this also solve the creating a new callback issue? stackoverflow.com/questions/42597602/…
in addition to this, you can send multiple parameter. const clickMe = (parameter1,parameter2) => (event) => { // Do something }
This one is also fired when your component is mounted, your code should be: onClick={(e) => clickMe(someParameter)(e)}
Similarly to if just clickMe, you can also destruct the event, even u do not define it as a parameter.
Thanks for this. It works. But why is there const clickMe = (parameter) => (event) => {...} instead const clickMe = (parameter) => {...} ?
|
24

Solution 1

function clickMe(parameter, event){
}

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

Solution 2 Using the bind function is considered better, than the arrow function way, in solution 1. Note, that the event parameter should be the last parameter in the handler function

function clickMe(parameter, event){
}

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

1 Comment

Could you please provide an explanation on the solution 2?
17

Currying with ES6 example:

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

Our button, that toggles handler:

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

If you want to call this function expression without an event object, then you'd call it this way:

clickHandler(1)();

Also, since react uses synthetic events (a wrapper for native events), there's an event pooling thing, which means, if you want to use your event object asynchronously, then you'd have to use 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.
};

Here's live example: https://codesandbox.io/s/compassionate-joliot-4eblc?fontsize=14&hidenavigation=1&theme=dark

7 Comments

Why do I still need to have event.persist() with console.log(event) but I don't need it with console.log(event.target)?
In this context, it is faster to use a normal function receiving 2 params than currying. you can run a benchmark test in jsben.ch
@ncesar How do you setup React in jsben.ch? Post your test plz.
@IsaacPak jsben is a simple tool to test javascript codes. You pretty much place two different samples of code and compare their speed. You don't have to put your entire React code, just a function that you think may be slower and you want to test. Also, I always use jsben.ch and jsbench.me just to make sure. In the clickHandler context, you would need to mock some codes. Like let event; so it wont throw an undefined error.
|
9

To solve the creating new callback issue completely, utilize the data-* attributes in HTML5 is the best solution IMO. Since in the end of the day, even if you extract a sub-component to pass the parameters, it still creates new functions.

For example,

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

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

See https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes for using data-* attributes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.