I have been using React for a while now, and I have become comfortable with the concept that I must manually bind my component methods to my component instance, as React made the decision to be "idiomatic" in not autobinding:
Therefore we decided not to have this built-in into React's class
model. You can still explicitly prebind methods in your constructor if
you want.
class Counter extends React.Component {
constructor() {
super();
this.tick = this.tick.bind(this);
}
tick() {
...
}
...
}
- https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html
We can clearly see the effects of this in this example http://jsbin.com/citafaradu/2/edit?js,console,output , from this similar question: How to properly bind current object context in ES6 using babelify
However, someone asked me recently whether there was any difference between prototype based classes and new, ES2015 classes. Intuitively, this answer should be an emphatic "no!", as the resulting instance objects will naturally have normal prototypes and behave... well, like JS objects! And furthermore, what would be the use of instance methods not bound to the instance?
I tried to search for any indication that this would be "idomatically" true of es6 classes, but all I turned up were other questions from React devs, with answers like this:
React's ES6 classes have no autobinding. This is documented here:
https://facebook.github.io/react/docs/reusable-components.html#no-autobinding
The reason is that javascript's ES6 classes have no autobinding
neither[sic]. React tries to not reinvent stuff that is already in
javascript. ES5 has no nice syntax for classes, so React had to invent
it's own classes. But now with ES6 classes we can just use standard
javascript.
- "cody", https://github.com/facebook/react/issues/4065
Now I was really confused. Was this perhaps a trick of the JSX transpilation? Taking a look at the output of the render method of the prior example:
{
key: "render",
value: function render() {
return React.createElement("div",null,
React.createElement("input", {
type: "text", onChange: this.handleBindedChange
}),
React.createElement("br", null),
React.createElement("input", {
type: "text", onChange: this.handleUnbindedChange
}),
React.createElement("br", null),
React.createElement("p",null,"Result: ",this.state.demo)
);
}
}
No dice here either - The babel output uses Object.defineProperty, which will absolutely bind functions added with it to the object they are attached to.
And so, I am at a loss. Most of the responses I found around this are older than the final es2015 spec - as I cannot find anything about it in the spec itself, was there a change that would have invalidated the React team's approach? Is this a strange artifact of transpilation that I have somehow misinterpreted? Is react doing something wacky behind the scenes to cause this? If so, why would they repeatedly claim that this was done to match the ES2015 standard? And if not, what is causing the behavior seen in the first example given?
See Question&Answers more detail:
os