ES6 方法未在 create-react-app 中定义
ES6 method is not defined in create-react-app
我很难理解为什么 create-react-app
无法编译,告诉我 error 'updateWord' is not defined no-undef
。我是 React with ES6 的新手。通常我会写一个像 const App = React.createClass({ });
这样的组件,但我决定尝试一些语法糖来代替。
我有父组件 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>
);
}
}
我试过将 updateWord(input)
改为 this.updateWord(input);
但无济于事。我得到:
"App.js:55 Uncaught TypeError: this.updateWord is not a function"
通常,当我实现与我现在正在做的类似的模式(使用 ES5)时,我没有任何困难。例如:
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>
);
}
}
问题是,当您在 this.handleInput
中执行 this.updateWord(...)
时,this
指的是 Input
组件。让我来说明问题:
当您设置 onInput
处理程序时,如下所示:
onInput={this.handleInput}
此处,由于您的 Input
组件正在调用该函数,因此 this
指的是 Input
组件。这是由于行:
this.props.onInput(input);
Input
组件正在调用 handleInput
。这意味着,在您的 handleInput
函数中,this
上下文是 Input
。考虑以下行:
this.updateWord(input);
在 handleInput
函数中。这里调用了 this.updateWord
,但是由于 this
是 Input
,它试图从不存在的 Input
调用 updateWord
,从而抛出错误。
解决方案是显式绑定 this
上下文 作为 class(App
组件) 而不是 Input
组件,使用 Function.prototype.bind
or an arrow function。来自文档:
The bind()
method creates a new function that, when called, has its this
keyword set to the provided value
您可以这样应用它:
onInput={this.handleInput.bind(this)}
或者更优选在构造函数中:
this.handleInput = this.handleInput.bind(this);
如果选择第二个选项,您可以执行以下操作:
onInput={this.handleInput}
(这更可取,因为 render
方法中的绑定将在每次渲染时创建一个新函数,这不是首选)。
上一行中的 this
上下文是 class。由于您绑定 this
,因此 class 将被正确用作函数中的 this
上下文,执行 this.updateWord
将调用该方法在class。
一种更好的方法是使用箭头函数而不是常规的 ES6 方法。来自文档:
An arrow function expression has a shorter syntax compared to function expressions and does not bind its own this
, arguments
, super
, or new.target
.
我们可以通过将 handleInput
分配给箭头函数而不是常规方法来应用它:
handleInput = (input) => {
console.log(`handle: ${input}`);
this.updateWord(input);
}
这将完全消除 bind
的使用,而是使用箭头函数。由于箭头函数不绑定它们自己的 this
,这意味着 this
指的是封闭的上下文。在上面的示例中,未使用方法,因此 this
指的是 class(封闭上下文)。这将正确调用 class 方法 updateWord
,因此,如果您走这条路,则无需更改 onInput
事件处理程序。
我很难理解为什么 create-react-app
无法编译,告诉我 error 'updateWord' is not defined no-undef
。我是 React with ES6 的新手。通常我会写一个像 const App = React.createClass({ });
这样的组件,但我决定尝试一些语法糖来代替。
我有父组件 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>
);
}
}
我试过将 updateWord(input)
改为 this.updateWord(input);
但无济于事。我得到:
"App.js:55 Uncaught TypeError: this.updateWord is not a function"
通常,当我实现与我现在正在做的类似的模式(使用 ES5)时,我没有任何困难。例如:
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>
);
}
}
问题是,当您在 this.handleInput
中执行 this.updateWord(...)
时,this
指的是 Input
组件。让我来说明问题:
当您设置 onInput
处理程序时,如下所示:
onInput={this.handleInput}
此处,由于您的 Input
组件正在调用该函数,因此 this
指的是 Input
组件。这是由于行:
this.props.onInput(input);
Input
组件正在调用 handleInput
。这意味着,在您的 handleInput
函数中,this
上下文是 Input
。考虑以下行:
this.updateWord(input);
在 handleInput
函数中。这里调用了 this.updateWord
,但是由于 this
是 Input
,它试图从不存在的 Input
调用 updateWord
,从而抛出错误。
解决方案是显式绑定 this
上下文 作为 class(App
组件) 而不是 Input
组件,使用 Function.prototype.bind
or an arrow function。来自文档:
The
bind()
method creates a new function that, when called, has itsthis
keyword set to the provided value
您可以这样应用它:
onInput={this.handleInput.bind(this)}
或者更优选在构造函数中:
this.handleInput = this.handleInput.bind(this);
如果选择第二个选项,您可以执行以下操作:
onInput={this.handleInput}
(这更可取,因为 render
方法中的绑定将在每次渲染时创建一个新函数,这不是首选)。
上一行中的 this
上下文是 class。由于您绑定 this
,因此 class 将被正确用作函数中的 this
上下文,执行 this.updateWord
将调用该方法在class。
一种更好的方法是使用箭头函数而不是常规的 ES6 方法。来自文档:
An arrow function expression has a shorter syntax compared to function expressions and does not bind its own
this
,arguments
,super
, ornew.target
.
我们可以通过将 handleInput
分配给箭头函数而不是常规方法来应用它:
handleInput = (input) => {
console.log(`handle: ${input}`);
this.updateWord(input);
}
这将完全消除 bind
的使用,而是使用箭头函数。由于箭头函数不绑定它们自己的 this
,这意味着 this
指的是封闭的上下文。在上面的示例中,未使用方法,因此 this
指的是 class(封闭上下文)。这将正确调用 class 方法 updateWord
,因此,如果您走这条路,则无需更改 onInput
事件处理程序。