简体   繁体   中英

How does React call the render function of an ES6 class in a such a way that `this` does not refer to the class itself?

For example, given the class with a function increaseQty

increaseQty() {
  this.qty++
}

and the call

render() {
  return (
    <div>
      <button onClick={this.increaseQty}>Increase</button>
    </div>
  )
}

this.qty will be undefined unless I write a line in my constructor binding the context of this in the constructor to the function

constructor(props) {
  super(props)
  this.qty = 0
  this.increaseQty = this.increaseQty.bind(this) // <---- like so
}

However this isn't the case in a normal es6 class if you're just using it normally:

https://jsfiddle.net/omrf0t20/2/

class Test {
  constructor() {
    this.qty = 0
  }

  increaseQty() {
    console.log(++this.qty)
  }

  doStuff() {
    this.increaseQty()
  }
}

const t = new Test()
t.doStuff() // prints 1

What aspect of React makes it so that render is called without the context of this ?

The difference here is that in your example with React you are passing increaseQty as a callback to another component, but in the second, you are calling it within the current context.

You can see the difference here in simplified example

class Test {
  constructor() {
    this.qty = 0
  }

  increaseQty() {
    console.log(++this.qty)
  }

  doStuff() {
    this.increaseQty(); // no need to bind
  }

  listenClicks() {
    // you should use bind to preserve context
    document.body.addEventListener('click', this.increaseQty.bind(this)); 
  }
}

React guidelines also recommend you bind methods in the constructor, to make the code more optimal, bind it once and always use the same function rather than create a new bound version for each render() call.

This isn't really an ES6 specific question (other than the fact that we are referencing a class and constructor). What you're doing in your function is just incrementing a value. If that value has not been initialized to something (even in ES5) then it will throw an error. You can't add 1 to undefined .

In ES5 (and ES6 really) this would be a problem:

var myObj = {
    addOne: function() {
        this.qty++;
    }
}

myObj.addOne(); // Error! this.qty is undefined

Whereas this would resolve it:

var myObj = {
    qty: 0,
    addOne: function() {
        this.qty++;
    }
}

myObj.addOne(); // Good to go

It's the same situation in your class. You cannot increment a variable that you haven't declared and initialized to a number value.

In an even simpler example this:

var x;

x++;

would throw an error whereas this:

var x = 0;

x++;

is good.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM