Search code examples
javascriptreactjsbind

in react bind what does 'this' refer to?


In the following example I'm trying to better understand the bind method. Specifically, what do the two instances of 'this' refer to and why do we need the second one? Also, why don't I need to include 'this' in the callback:

UPDATE:

I understand now that they both refer to FontChooser but why do we want to bind FontChooser.checkbox to FontChooser? Isn't that redundant? or in other words if 'this' refers to the class why do we need to bind a class callback (this.checkbox) to the class (this.checkbox.bind(this))?

It's almost like we are binding a specific instance back to the class callback but (a) where are we creating the specific instance and (b) shouldn't the specific instance already have the class callback

class FontChooser extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      hidden: true,
      checked: this.props.bold ? true : false
    };
  }

  displayButtons() {
    this.setState({
      hidden: !this.state.hidden
    });
  }

  checkbox() {
    //why not checkbox(this){
    this.setState({ checked: !this.state.checked });
  }

  render() {
    console.log(this.state);
    var weight = this.state.checked ? "bold" : "normal";

    return (
      <div>
        <input
          type="checkbox"
          id="boldCheckbox"
          hidden={this.state.hidden}
          checked={this.state.checked}
          onChange={this.checkbox.bind(this)}
        />
        <button id="decreaseButton" hidden={this.state.hidden}>
          {" "}
          -{" "}
        </button>
        <span id="fontSizeSpan" hidden={this.state.hidden}>
          {" "}
          {this.state.size}
        </span>
        <button id="increaseButton" hidden={this.state.hidden}>
          {" "}
          +{" "}
        </button>
        <span
          id="textSpan"
          style={{ fontWeight: weight, fontSize: this.state.size }}
          onClick={this.displayButtons.bind(this)}
        >
          {" "}
          {this.props.text}
        </span>
      </div>
    );
  }
}

Solution

  • In javascript, the this keyword points to a different object depending on the context it was executed in. When using a function in the JSX 'template', the function is not executed within your class, but in some other context in React. As a consequence, whatever this refers to, is changed.

    One was to work around this, is using the bind() method. This method will replace whatever function it is used on, and replace whatever the this keyword points to, to a new location you provided.

    In your example, you're using this.displayButtons.bind(this). Here, this refers to this class (FontChooser), and will make sure that this will point to that class regardless of the execution context.

    Take a look at the MDN documentation, there are also easy to understand examples. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind