0

I am relatively new to es6 and react. I was following up a tutorial on creating react components and wondered if es6 arrow functions would work same while defining the component functions. Given the lexical scope of 'this' while using arrow functions, i thought it would work.

But 'this' object seems to be resolving to 'undefined' in babel transpiled code. Any specific explanation on why this does not resolve to the defining component variable ? Although using method shorthand and extending es6 classes works, i am just curious.

Component with arrow functions:

const PromptContainer = React.createClass({
  getInitialState: () => ({
    username: '',
  }),
  onInputChange: (e) => {
    this.setState({
      username: e.target.value,
    });
  },
  render: () => (
    <div className="jumbotron col-sm-6 col-sm-offset-3 text-center">
      <h1>{this.props.header}</h1>
      <div className="col-sm-12">
        <form>
          <div className="form-group">
            <input
              className="form-control"
              type="text"
              onChange={this.onInputChange}
              placeholder="Github Username"
              value={this.state.username}
            />
          </div>
        </form>
      </div>
    </div>
  ),
});
aga5tya
  • 55
  • 9

2 Answers2

3

Given the lexical scope of 'this' while using arrow functions, i thought it would work.

Then you are misunderstanding the meaning of lexical scope. It does the opposite of what you want.

var foo = () => this;

is almost exactly like

var _temp = this;
var foo = () => _temp;

which means

const PromptContainer = React.createClass({
  getInitialState: () => {
    this;
  },
  onInputChange: (e) => {
    this;
  },
  render: () => {
    this;
  },
});

is

var _temp = this;

const PromptContainer = React.createClass({
  getInitialState: () => {
    _temp;
  },
  onInputChange: (e) => {
    _temp;
  },
  render: () => {
    _temp;
  },
});

so none of your functions ever access this of the function, they access the this of that exists outside the createClass call, which is `undefined.

If you want a short way to write what you want, use concise method syntax:

const PromptContainer = React.createClass({
  getInitialState() {
    this;
  },
  onInputChange(e) {
    this;
  },
  render() {
    this;
  },
});
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • In react class es6 format, the below one works, is the transpiler responsible for binding 'this' context to be of the class component ? `class Button extends React.Component { // Use an arrow function here: handleClick = () => { console.log('clickity'); } render() { return ( // this binding works – aga5tya Jul 06 '16 at 18:19
  • The `class Foo { prop = () => { /* stuff */}; }` syntax is an experimental proposed syntax, and that syntax defines the `this` in that case to be the instance of the class, so it has a similar behavior to autobinding, but is not quite the same, because autobinding results in one copy of the function with many bound functions, and this syntax results in many copies of the function. – loganfsmyth Jul 06 '16 at 18:38
0

You should bind this to the event handler method:

onChange={this.onInputChange.bind(this)}
Harmen
  • 22,092
  • 4
  • 54
  • 76