简体   繁体   English

在 create-react-app 中未定义 ES6 方法

[英]ES6 method is not defined in create-react-app

I'm having difficulty understanding why create-react-app is unable to compile, telling me that error 'updateWord' is not defined no-undef .我很难理解为什么create-react-app无法编译,告诉我error 'updateWord' is not defined no-undef I'm fairly new to React with ES6.我对使用 ES6 进行 React 相当陌生。 Normally I would write a component like const App = React.createClass({ });通常我会写一个像const App = React.createClass({ });这样的组件const App = React.createClass({ }); but I've decided to try out some syntactical sugar instead.但我决定尝试一些语法糖。

I have parent component App and a child component Input :我有父组件App和子组件Input

class App extends Component {
  constructor(props) {
    super(props);
    // all other code omitted...
  }

  handleInput(input) {
    console.log(`handle: ${input}`); 
    updateWord(input);
    // this also causes an error
    // this.updateWord(input);
  }

  updateWord(input) {
    console.log(`update ${input}`);
    // why isn't this defined?
  }

  render() {
    return (
      <div className="App">
        <Input onInput={this.handleInput} />
      </div>
      );
  }
}

class Input extends Component {
  handleInput(e) {
    let input = e.target.value;
    this.props.onInput(input);
  }

  render() {
    return (
      <form>
        <input onChange={this.handleInput.bind(this)} />
      </form>
      );
  }
}

I've tried changing to this.updateWord(input);我试过this.updateWord(input); instead of updateWord(input) but to no avail.而不是updateWord(input)但无济于事。 I get:我得到:

"App.js:55 Uncaught TypeError: this.updateWord is not a function" 

Normally when I implement a similar pattern (with ES5) to what I'm doing now I have no difficulties.通常,当我实现与我现在所做的类似的模式(使用 ES5)时,我没有任何困难。 For example:例如:

const App = React.createClass({
  getInitialState: function() {
    // all other code omitted...
  },

  handleInput: function(input) {
    console.log(`handle: ${input}`); 
    this.updateWord(input);
  },

  updateWord: function(input) {
    console.log(`update ${input}`);
    // In theory, this implementation would not cause any errors?
  },

  render: function() {
    return (
      <div className="App">
        <Input onInput={this.handleInput} />
      </div>
      );
  }
}

The problem is that when you do this.updateWord(...) in this.handleInput , this refers to the Input component.问题是,当你做this.updateWord(...)this.handleInputthis指的是Input组件。 Let me illustrate the problem:让我来说明这个问题:

When you set the onInput handler, like so:当您设置onInput处理程序时,如下所示:

onInput={this.handleInput}

Here, since your Input component is calling the function, this refers to the Input component.在这里,由于您的Input组件正在调用该函数, this指的是Input组件。 This is due to the line:这是由于以下行:

this.props.onInput(input);

The Input component is calling handleInput . Input组件正在调用handleInput That means, in your handleInput function, the this context is Input .这意味着,在您的handleInput函数中, this上下文是Input Consider the line:考虑这一行:

this.updateWord(input);

in the handleInput function.handleInput函数中。 Here you call this.updateWord , but since this is Input , it tries to call updateWord from Input which does not exist, thus throwing the error.在这里您调用this.updateWord ,但由于thisInput ,它尝试从不存在的Input调用updateWord ,从而updateWord错误。


The solution is to explicitly bind the this context as the class ( App component) instead of the Input component, using either Function.prototype.bind or an arrow function .解决方案是使用Function.prototype.bind箭头函数this上下文显式绑定为类( App组件)而不是Input组件。 From the documentation:从文档:

The bind() method creates a new function that, when called, has its this keyword set to the provided value bind()方法创建一个新函数,当调用this函数时,将其this关键字设置为提供的值

You can apply it like so:您可以像这样应用它:

onInput={this.handleInput.bind(this)}

Or more preferably in the constructor:或者更优选地在构造函数中:

this.handleInput = this.handleInput.bind(this);

With the second option you may then do:使用第二个选项,您可以执行以下操作:

onInput={this.handleInput}

(This is more preferable as binding in the render method will create a new function every time on render, which isn't preferred). (这更可取,因为render方法中的绑定将在每次render时创建一个新函数,这不是首选)。

The this context in the line above is the class.上一行中的this上下文是类。 Since you bind this , the class will be correctly used as this context in the function and executing this.updateWord will invoke the method in the class .由于您绑定了this该类将被正确用作函数中的this上下文,并且执行this.updateWord将调用该类中的方法。

An even more preferable way is to use arrow functions instead of regular ES6 methods.更可取的方法是使用箭头函数而不是常规的 ES6 方法。 From the documentation:从文档:

An arrow function expression has a shorter syntax compared to function expressions and does not bind its own this , arguments , super , or new.target .与函数表达式相比,箭头函数表达式的语法更短,并且不绑定自己的thisargumentssupernew.target

We can apply this by assigning handleInput to an arrow function instead of a regular method:我们可以通过将handleInput分配给箭头函数而不是常规方法来应用它:

handleInput = (input) => {
    console.log(`handle: ${input}`); 
    this.updateWord(input);
}

This will eliminate the use of bind completely and instead, use arrow functions.这将完全消除bind的使用,而是使用箭头函数。 Since arrow functions don't bind their own this , it means this refers to the enclosing context.由于箭头函数不绑定自己的this ,这意味着this指的是封闭的上下文。 In the example above, a method is not used thus this refers to the class (the enclosing context).在上面的例子中,没有使用方法,因此this指的是类(封闭上下文)。 That will correctly call the class method updateWord , and consequently, you need not change the onInput event handler if you go this route.这将正确调用类方法updateWord ,因此,如果您走这条路线,则无需更改onInput事件处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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