Passing Functions to React Components
How do I pass an event handler to a component?
<MyComponent onClick={this.handleClick}>
In React, there are several cases where you may want to pass a function (like onClick
) as a prop from a container to a child component — usually in order to let the child notify the parent of some event.
For example:
Assuming that you will probably need to have access to the parent component’s state
or props
from the child component, you will need to somehow bind the function to the parent component instance.
While there are a few ways to do that, some are better solutions.
How Do I Bind a Function to a Component Instance?
Depending on the syntax and build steps involved, there are many ways to ensure that functions have access to component attributes such as props
and state
.
1. Bind in constructor
While this a widely used method, it is a somewhat strange one that involves the use of the obscure word bind
and requires an unnecessary line of code (we will discuss that later).
In my opinion, it is not the best way.
2. Bind in render
Although we supposedly save a line of code with this approach compared to the previous one, this method is still somewhat unclear and I do not recommend using it.
In addition, and perhaps more importantly:
“Using
.bind(this)
inside render, creates a new function each time the component renders, which may have performance implication.” — React’s documentation
3. Arrow function
An arrow function expression has a shorter syntax than a function expression and does not have its own this
. For this reason, you can pass it to the child component and still access the parent’s props
and state
.
In my opinion, this is the best way:
Note: According to React’s documentation, “This syntax is experimental and not standardized yet.”
Passing Parameters to an Event Handler
Examine carefully if you really need to pass parameters through the function prop to the child.
Check if you have other options, such as passing the parameter as a prop or figuring out that you don’t really need the parameter in the child component.
Why am I saying this?
As mentioned before, using syntax like bind in render or an anonymous function (like in the next example) will cause the child component to re-render after each and every render of the parent — regardless of whether was changed is relevant to its child or not. That means poor performance.
As the child component receives an anonymous function as a prop, it cannot compare with the previous anonymous function (because both are anonymous). However, passing a reference to the method likeonClick={this.handleClick}
lets React know that nothing has changed, so it does not re-render unnecessarily.
Example of what you shouldn’t do if you do not have to:
<button onClick={() => this.handleClick(id)} />
Note, however, that the anonymous function is sometimes inevitable (e.g. when we only need to pass an argument in the context).
Living proof
Check out the next CodeSandbox example. It demonstrates two ways of passing a function to a component as props. The first passes a function by reference, and the second passes an anonymous function.
When you click the button, the number near each of the components indicates how many times it was rendered.
Can you guess which one would render more times unnecessarily?
Conclusion
I hope this article helped you to understand how you can — and should — pass functions between components in a simple and efficient way.
Have a great day! Thanks for reading!