Getting out of a .bind()
Thanks to class properties, never bind “this” to methods in class constructors again. 🎉
The Short
Instead of this:
class MyClass extends React.PureComponent {
constructor() {
this.myFunction = this.myFunction.bind(this);
} myFunction() {
const { myVar } = this.props;
}
... etc
}
With class properties enabled in Babel, bound class methods are simple:
class MyClass extends React.PureComponent {
myFunction = () => {
const { myVar } = this.props;
}
... etc
}
The Long
When people start out with React they might create a simple increment counter demo:
Everything renders correctly on load and render
is referencing this.state.count
as expected. However, after clicking the “increment” button you’ll see the increment
method throw an error:
Cannot read property 'state' of undefined
Weird, why could ‘render’ access state but not ‘increment’?
Method’s are bound to the class instance’s this
value, however browsers invoke event handlers with a different context.
To fix the problem, we write this unintuitive line of code:
constructor() {
super(); this.state = {
count: 0,
} this.increment = this.increment.bind(this)
}
Gross.
Class Fields / Properties to the Rescue
Class Fields are a stage 3 proposal that you can use right now with Babel. They allow us to write the previous example like so:
You see how we’re using =
to declare state
and increment
? With this proposal, these two class variables are declared in the context of the class instance, aka this
.
Thus, the this.state = {}
inside of the constructor method is analogous to state = {}
outside of the method.
In the case of increment
, we set an arrow function which inherits the lexical scope. Lexical scope? Put simply, it inherits from it’s outer context, which in this case is our component instance.