Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why and when do we need to bind functions and eventHandlers in React?

Tags:

class SomeClass extends Component{   someEventHandler(event){   }   render(){     return <input onChange={------here------}>   } } 

I see different versions of ------here------ part.

// 1 return <input onChange={this.someEventHandler.bind(this)}>  // 2 return <input onChange={(event) => { this.someEventHandler(event) }>  // 3 return <input onChange={this.someEventHandler}> 

How are the versions different? Or is it just a matter of preference?


Thank you all for answers and comments. All are helpful, and I strongly recommend to read this link FIRST if you are confused as me about this.
http://blog.andrewray.me/react-es6-autobinding-and-createclass/

like image 435
kukrt Avatar asked Dec 13 '16 04:12

kukrt


People also ask

Why do we need to bind event handler in React?

Output: Now if we run the application and click on the button, we get an error. This is because this returns an “undefined”. This is why we need to bind our events. Binding Event Handler in Render Method: We can bind the handler when it is called in the render method using bind() method.

Why do you need to bind methods in React?

bind(something) returns a new function, in which references to this will refer to something . This is a way of saving the current value of this , which is in scope during the call to the constructor, so that it can be used later when the function is called.

What is binding event handlers in React?

To bind event handlers in React, the simplest, and the efficient way is to bind with arrow functions. Since this a new feature, it is not uncommon to see a lot of code using the binding in the constructor method. This is an equally efficient option to use.

Do we need to bind Arrow function in React?

In ReactJs, when we are working with class-based components and want to access this inside a class method. This will need to bind it. Binding this allows it to access the state and setstate inside the class. To avoid the need for binding we have something introduced in ES6 as arrow functions.


2 Answers

Binding is not something that is specifc to React, but rather how this works in Javascript. Every function / block has its own context, for functions its more specific to how its called. The React team made a decision for this to not be bound on custom methods on the class (aka not the builtin methods like componentDidMount), when adding ES6 support (class syntax).

When you should bind the context depends on the functions purpose, if you need to access props, state or other members on the class, then you would need to bind it.

For your example, each is different and it depends on how your component is set up.

Pre binding to your class

.bind(this) is used to bind the this context to your components function. However, it returns a new function reference each render cycle! If you don't want to bind on each usage of the function (like in a click handler) you can pre-bind the function.

a. in your constructor do the binding. aka

class SomeClass extends Component{     constructor(){         super();         this.someEventHandler = this.someEventHandler.bind(this);     }     someEventHandler(event){     }     .... }  

b. make your custom functions on the class fat arrow functions. aka

class SomeClass extends Component{     someEventHandler = (event) => {     }     .... } 

Runtime binding to your class

few common ways to do this

a. you can wrap your components handler function with an inline lambda (fat arrow) function.

onChange={ (event) => this.someEventHandler(event) } 

this can provide additional functionality like if you need to pass additional data for the click handler <input onChange={(event) => { this.someEventHandler(event, 'username') }>. The same can be done with bind

b. you can use .bind(this) as described above.

onChange={ this.someEventHandler.bind(this) } 

with additional params <input onChange={ this.someEventHandler.bind(this, 'username') }>

If you want to avoid creating a new function reference but still need to pass a parameter, its best to abstract that to a child component. You can read more about that here

In your examples

// 1 return <input onChange={this.someEventHandler.bind(this)}> 

This is just doing a runtime event handler bind to your class.

// 2 return <input onChange={(event) => this.someEventHandler(event) }> 

Another runtime bind to your class.

// 3 return <input onChange={this.someEventHandler}> 

You are just passing the function as the callback function to trigger when the click event happens, with no additional parameters. Make sure to prebind it!

To summarize. Its good to think about how to optimize your code, each method has a utility / purpose depending on what you need.

like image 77
John Ruddell Avatar answered Oct 06 '22 22:10

John Ruddell


Why bind a React function?

When you define a component using an ES6 class, a common pattern is for an event handler to be a method on the class. In JavaScript, class methods are not bound by default. If you forget to bind this.someEventHandler and pass it to onChange, this will be undefined when the function is actually called.

Generally, if you refer to a method without () after it, such as onChange={this.someEventHandler}, you should bind that method.

There three ways to bind your onChange function to the correct context

First

return <input onChange={this.someEventHandler.bind(this)}> 

In this one we make use of bind explicitly to function to make the onChange event available as an argument to the eventHandler. We can also send some other parameter with type of syntax like

return <input onChange={this.someEventHandler.bind(this, state.value)}> 

Second

return <input onChange={(event) => { this.someEventHandler(event) }> 

This is a ES6 syntax, whereby we can specifythe parameters that we want to pass to the someEventHandler function. This is equivalent to .bind(this) however, It also gives us the flexibility to send other attributes along with the event like

return <input onChange={(event, value) => { this.someEventHandler(event, value) }> 

Third

Define the function someEventHandler using Arrow function

someEventHandler = () => {     console.log(this); // now this refers to context of React component } 

An arrow function does not have its own this, the this value of the enclosing execution context is used and hence the above function gets the correct context.

or bind it in constructor like

constructor(props) {    super(props);    this.someEventHandler = this.someEventHandler.bind(this); }   return <input onChange={this.someEventHandler}> 

In this method, event is directly attached to the someEventHandler function. No other parameters can be passed this way

like image 37
Shubham Khatri Avatar answered Oct 07 '22 00:10

Shubham Khatri