Lexical scope of 'this' in React.createCla

2019-09-13 01:19发布

问题:

This question already has an answer here:

  • Are 'Arrow Functions' and 'Functions' equivalent / exchangeable? 2 answers

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>
  ),
});

回答1:

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;
  },
});


回答2:

You should bind this to the event handler method:

onChange={this.onInputChange.bind(this)}