user9226007
user9226007

Reputation:

Passing an arrow function vs passing the function

Say I have a function:

handleChange = (e) => {
  this.setState({ [e.target.id]: e.target.value });
}

What is the difference between the following:

1.

<FormControl value={this.state.password} onChange={this.handleChange} />
<FormControl value={this.state.password} onChange={(e) => this.handleChange(e)} />

Upvotes: 15

Views: 6327

Answers (6)

Nitish Phanse
Nitish Phanse

Reputation: 562

Assuming your event handler is written like so in your class

handleChange = (e) => {
  this.setState({ [e.target.id]: e.target.value });
}

Let us go to the first example that you have mentioned.

<FormControl value={this.state.password} onChange={this.handleChange} />

Over here, for every change you are passing the memory reference of the handleChange function, and to it the event object is being passed.

Going to the second method.

<FormControl value={this.state.password} onChange={(e) => this.handleChange(e)} />

Here you are creating a new anonymous function, which takes the event object as a parameter, every time an event change occurs. This drastically increases garbage collection if you have large list items.Adding an arrow function in this case is redundant as the context is already bound due to the way you wrote you handleChange method initially. As a perf tip, if you are using arrow functions in your classes, use option 1 for event handlers.

Upvotes: 6

Saeed Seyfi
Saeed Seyfi

Reputation: 637

Using arrow function in render may cause some performance issues.

I'd suggest you to use arrow function in class property, but you must use stage-2 features.

Here you'll find a nice comparison between the options:

https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56

Upvotes: 1

Prakash Naidu
Prakash Naidu

Reputation: 780

We can bind our event handlers in class constructor:

we can now access to this inside the event handle

class MyClass extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
  }
  handleChange(){
   //you can now access "this" inside handlechange
  } 

}

Looks fine. When we add more event handlers to our class, code should look similar to this:

import React, { Component } from 'react'
import { MyInput, MyAnotherInput } from 'myInputs'

class MyComponent extends Component {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
    this.handleClick = this.handleClick.bind(this)
    this.handleKeyPress = this.handleKeyPress.bind(this)
  }

  handleChange(e) {
    e.preventDefault()
  }

  handleClick(e) {
    e.preventDefault()
  }

  handleKeyPress(e) {
    e.preventDefault()

    if (e.nativeEvent.keyCode === 13) {
      console.log('This is enter!')
    }
  }

  render() {
    return (
      <div>
        <MyInput
          onChange={ this.handleChange }
          onClick={ this.handleClick }
          onKeyPress={ this.handleKeyPress }
        />
        <MyAnotherInput
          onChange={ this.handleChange }
          onClick={ this.handleClick }
          onKeyPress={ this.handleKeyPress }
        />
      </div>  
    )
  }
}

This is, what we can do with Babel compiler with es2015 as preset configuration.

Event handlers with arrow functions

As you have probably seen, when we create event handler method, we always need to add this to constructor, to bind this. Quite tiresome. To be honest, there is no sense to create constructor method only for binding your methods. There should be another solution, and there is.

All what you need is to install stage-1 Babel preset and use arrow functions. If you don’t know, how to do this, go to Babel documentation, it’s very good.

In our case instead of binding methods to this we can writ something like this:

render() {
   return(<MyInput onChange={ (e) => this.handleOnChange(e) } />)
}

We have created new anonymous function, which automatically bind this, that’s why we don’t need to use .bind() method. We have still the same methods in class, and new arrow functions as wrappers in callbacks properties.

This is still not perfect solution, because we need to update parameters in arrow function wrappers and we create new instances each time when render method is triggered. Arrow functions in React properties are also not great idea.

Upvotes: 0

Tianzhen Lin
Tianzhen Lin

Reputation: 2614

When handling an event in JavaScript, the this context out of the box can be very confusing, you can read more about it in this excellent writeup.

Back to your question, the first way onChange={this.handleChange} does not guarantee the this context in handleChange() would always be the same component instance, in many cases, this would refer to the FormControl instance that emits the onChange event.

The second way uses arrow syntax, it would guarantee this would always be the React component instance that handles the event.

In short, using arrow syntax for event handling is preferred in React component classes because it guarantees a consistent this context.

Upvotes: -3

Felix Kling
Felix Kling

Reputation: 816394

In the first case you are using handleChange as event handler.

In the second case you are using a new function as event handler, which in turn calls handleChange.

The difference is that there will be two function calls in the second example. Otherwise they are the same.

In other words: there is no need to use the second form, and it can even be disadvantageous for rerendering.

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281676

The second case an anonymous function is created which executes the handleChange method and and thereby providing it the context.

Everytime the React component renders, a new function is created in the second and not in the first case since the same reference of handleChange method is being provided to the handler.

You might also want to look at how arrow function in render achieve context binding

Upvotes: 8

Related Questions