7

I can't understand why this.click = this.click.bind(this) is needed and what is it doing.

class MyComponent extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                name: 'Initial State'
            };
            this.click = this.click.bind(this);
        }
        click() {
            this.setState({
                name: 'React Rocks!'
            });
        }
        render() {
        return (
            <div>
            <button onClick = {this.click}>Click Me</button>
            <h1>{this.state.name}</h1>
            </div>
        );
      }
    };
Sid24
  • 334
  • 3
  • 14

4 Answers4

9

If you didn't use bind(), when this.click() was called from the event listener, the value of this would not be your React component (where state and props etc. are), but instead this would be the function this.click() itself. Normally, every time a function is called, the execution context - the value of this - is set to the function itself.

Of course, that's not such a good thing if you want to access the context of your React component. bind() is one way to ensure a function runs with the same execution context of your component, giving you access to this.state, this.props etc. inside your function. Another way is to use the ES6 arrow function declaration:

let foo = () => {console.log("bar")}

Which automatically sets the value of this for foo to whatever context the function was declared in. If you declare foo in the same context as your React component, it will retain that context, thus ensuring that the value of this is the same inside of foo.

jered
  • 11,220
  • 2
  • 23
  • 34
  • 2
    I'd just like to point out something about es6 arrow functions and react... You will see a lot of examples where people declare `onClick={ () => { _function_body_ } }` inside the `render()` method. You should refrain from doing this because it will cause a performance hit by redefining the function on every render call. This is not what @jered is suggesting just btw. – Kyle Richardson Jul 20 '17 at 18:07
  • Ok so if my Click() function inside its code hadn't used "this" then bind wouldn't be needed, am i right? – Sid24 Jul 20 '17 at 18:25
  • 1
    @Sid24 That is correct. If your function - for example - simply takes an argument and returns a result and doesn't need access to your component state, props, or functions, then you would not need to bind it. – jered Jul 20 '17 at 18:44
3

Accorging to React Documentation binding is necessary because class methods are not bound by default. And if you pass a callback to an event handler without binding, 'this' will be undefined.

You can use property initializers to bind your callbacks:

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: 'Initial State'
        };
    }
    handleClick = () => {
        this.setState({
            name: 'React Rocks!'
        });
    }
    render() {
        return (
          <div>
          <button onClick = {this.handleClick}>Click Me</button>
          <h1>{this.state.name}</h1>
          </div>
      );
    }
};

You can also use an arrow function in the callback:

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: 'Initial State'
        };
    }
    handleClick() {
        this.setState({
            name: 'React Rocks!'
        });
    }
    render() {
        return (
          <div>
          <button onClick = {() => this.handleClick()}>Click Me</button>
          <h1>{this.state.name}</h1>
          </div>
      );
    }
};
Sid24
  • 334
  • 3
  • 14
kulaeff
  • 453
  • 3
  • 12
2

You need to do it because the callback function is called with a different context. By performing .bind( this ) you ensure that the function is always invoked with the same this context as your component.

Editted: per @jered's comment.

Kyle Richardson
  • 5,567
  • 3
  • 17
  • 40
  • Note that you don't have to use `.bind(this)` if the function is an arrow function. – cssko Jul 20 '17 at 18:00
  • You're mostly correct, however when we're talking about `this` we're talking about _context_, not _scope_. Context and scope are different (albeit related) things but are often confused for each other, and I think it's important to keep the distinction. `bind()` does not alter the lexical scope of the resulting function, only its context. – jered Jul 20 '17 at 18:50
1

Without it you should get undefined when you call your click() function. From the react docs...

You have to be careful about the meaning of this in JSX callbacks. In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

Check out the documentation for some more details here: https://facebook.github.io/react/docs/handling-events.html

justDan
  • 2,302
  • 5
  • 20
  • 29