6

I don't understand why I need

this.handleChange = this.handleChange.bind(this);

to make my program work:

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = { foo: 1 }
    }

    render() {
        return (
                <div>
                <input onChange={this.handleChange} value="xxx" />
                <span>yes {this.state.foo}</span>

                </div>



        );
    }

    handleChange(e) {
        console.log("called 1");
        this.setState({foo: this.state.foo+1});
    }

}


ReactDOM.render(<Foo />, document.getElementById("name1") )

In other words, what does

this.handleChange = this.handleChange.bind(this);

do in layman's terms

american-ninja-warrior
  • 7,397
  • 11
  • 46
  • 80
  • I am not familiar with react, but if you do something similar in angularJs, it means that you are binding the scope of this, to your method. – John Dec 19 '18 at 07:51
  • This means you are binding the scope of current object to the method. – Adnan Dec 19 '18 at 07:53

1 Answers1

6

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.

This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.

If calling bind annoys you, there are two ways you can get around this. you can use the experimental public class fields syntax or arrow functions in the callback:

Arrow Function Example:

    class LoggingButton extends React.Component {
  handleClick() {
    console.log('this is:', this);
  }

  render() {
    // This syntax ensures `this` is bound within handleClick
    return (
      <button onClick={(e) => this.handleClick(e)}>
        Click me
      </button>
    );
  }
}
onejeet
  • 1,191
  • 6
  • 14
  • 1
    There's a drawback do this method. Since you will be change the onClick function handler at render execution, causing a change in the virtual dom and ultimately the actual dom at each render. A solution is to already declare the function as an arrow function: handleClick = (e) => { console.log(this); } – Gabriel Ferrarini Dec 19 '18 at 08:21
  • this is called public class fields syntax, that I mentioned in the answer. It's in the draft, not yet part of JS. but fully supported if using babel. – onejeet Dec 19 '18 at 09:31