0

I am using react hooks and functional components and was wondering how I can add multiple params to an react onClick event.

I know there are different options to achieve this. In the past I used this style below (from https://reactjs.org/docs/handling-events.html):

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={() => this.handleClick()}>
        Click me
      </button>
    );
  }
}

But now I am facing this exact described problem from the official react docs. I am getting to many rerenders because of these arrow functions in the onClick attribute:

The problem with this syntax is that a different callback is created each time the LoggingButton 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.

I have put my function already in a useCallback hook. But if I use this function in a onClick event with an arrow function it will trigger rerenders again. If I change it to the function reference only it is not triggering rerenders. So far this is fine.

But: How do I add multiple parameters to this functionreference when using react hooks and functional components.

Will I get by default always the e (event parameter?) as first parameter? Can somebody explain to me when and how I am getting the react event parameter and when I will not receive this event? How can I add multiple params beside the event parameter in my onClick attribute?

For example:

What if I have this function and want to use it in the react onClick attribute, prevent unnecessary rerender and add multiple different parameter in the function call

const myClickFunction = (e, value1, value2, value3) => {
    // ...
}


// this would trigger rerenders because of the arrow function how do I prevent this?
<button onClick={(e) => myClickFunction(e, "input1", "input2", "input3")}>
    Click me
</button>

anvin
  • 450
  • 2
  • 8
  • 22
  • 1
    Does this answer your question? It explains how you can bind a function and use it with onClick while passing parameters in both the old ES5 way and new ES6 way: https://stackoverflow.com/questions/29810914/react-js-onclick-cant-pass-value-to-method – olawrdhalpme Mar 18 '21 at 14:52

1 Answers1

2

One trick I like to use in this case is to "bind" the parameters to rendered element using data attributes

const myClickFunction = (e) => {
    const value1 = e.currentTarget.getAttribute('data-value1')
    const value2 = e.currentTarget.getAttribute('data-value2')
    const value2 = e.currentTarget.getAttribute('data-value2')
}


// this would trigger rerenders because of the arrow function how do I prevent this?
<button onClick={myClickFunction} data-value1="a" data-value2="b" data-value3="c">
    Click me
</button>

This way you can memoise your function using useCallback safely and you can reuse the same function if you want to pass it to array of children for example. This is not ideal, you couple parents and children and you can only use data which is serializeable to string (basically only primitives).

Better solution would be to store your values somewhere out of component tree so you can access them without closures (for example in redux-thunk you don't need to pass a lot of stuff around, you can just get data you need from store directly by calling getState)

dkuznietsov
  • 298
  • 1
  • 9
  • 1
    Thanks for your answer! This is an interesting approach. Is this best practice? Is there no other way to do this? – anvin Mar 23 '21 at 09:16