6

So i'm reading a book on React which said I have to bind my methods like

this.onClickMe = this.onClickMe.bind(this);

but it looks to work just fine without using the above code

class ExplainBindingsComponent extends Component {
  onClickMe() {
    console.log(this);
  }
  render() {
    return (
      <button
        onClick={ () => { this.onClickMe() } }
        type="button"
      >
        Click Me
  </button>
    );
  }
}

but it's saying I should do something like this,

class ExplainBindingsComponent extends Component {
  constructor() {
    super();
    this.onClickMe = this.onClickMe.bind(this);
  }
  onClickMe() {
    console.log(this);
  }
  render() {
    return (
      <button
        onClick={this.onClickMe}
        type="button"
      >
        Click Me
  </button>
    );
  }
}

is this.onClickMe = this.onClickMe.bind(this); still something I have to do? and if so what does it do vs my above example

  • 1
    In your first example, your button will re-render each time the parent's props change due to passing an anonymous function to `onClick`. React thinks that the `onClick` handler has changed since a new function will be created on each render – Hunter McMillen May 11 '18 at 17:54

5 Answers5

13

There are multiple ways to bind your function to the lexical context of the React class,

  • one such method is to bind it in the constructor,

  • other method is to use class fields as arrow functions, and

  • the third way to bind in the render using .bind or arrow,

Each of these can be used, however its best to avoid binding in the render since a new function is returned on each render

Using class field as arrow function.

class ExplainBindingsComponent extends Component {
  onClickMe = () => {
    console.log(this);
  }
  render() {
    return (
      <button
        onClick={ this.onClickMe }
        type="button"
      >
        Click Me
  </button>
    );
  }
}

Binding in render

onClick={() => this.onClickMe() }

or

onClick={this.onClick.bind(this)}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 1
    I think if you use the arrow function, then every instance gets its own copy of that method rather than all instances sharing one copy of the method. It definitely messes with inheritance, if you are into that kind of thing. – Ziggy Sep 13 '19 at 07:24
2

is this.onClickMe = this.onClickMe.bind(this); still something I have to do?

You don't have to do it if you use arrow functions that capture lexical this. But it is considered to be a best practice because it allows you to avoid function creation inside render.

render() {
    return (
      <button
        /* creates new function on every render call*/
        onClick={ () => { this.onClickMe() } }
        type="button"
      >
        Click Me
  </button>
    );
  }

vs

constructor() {
    super();

    // creates function once per component instance
    this.onClickMe = this.onClickMe.bind(this);
  }
Yury Tarabanko
  • 44,270
  • 9
  • 84
  • 98
1

In your case, you don't need to because you use arrow function where this is bound to a context in which arrow function is defined - in this case to your component.

this.onClickMe = this.onClickMe.bind(this)

it's necessary when you pass function without any binding so it might be invoked where this will point to another object.

Tomasz Mularczyk
  • 34,501
  • 19
  • 112
  • 166
0

For anyone who is following 'React Step by Step' link and got stuck because in the example Clock, they haven't written any bind and it has worked well, but on the next example Toggle, they started to use bind(this).

Well, you can see the function tick(){...} (Clock class) and handleClick (){...} (Toggle class) are similar, as they both use the word this inside. Well the difference between them is how they are called. In the first (Clock), it is called using arrow function (inside componentDidMount() method) and using it allows you to bind automatically the word this with the object. On the other hand, the second method is not using ()=>{}, and need to bind this with the object. So for this purpose the assignment this.handleClick = this.handleClick.bind(this); helps you.

jcruz
  • 1
0

There are 3 ways to bind this

  1. While defining the state. Like this:

    this.state = { this.eventHandler = this.eventHandler.bind(this) }

  2. Change the normal function to arrow function. Like this:

    eventHandler = () => { console.log('event handler'); }

  3. Pass arrow function directly into the props. Like this:

    <input onClick={(e) => this.eventHandler(e) } />

Hope this could resolve your problem. ~RDaksh

Rahul Daksh
  • 212
  • 1
  • 7