React - TypeError: Cannot read property 'props' of undefined
React - TypeError: Cannot read property 'props' of undefined
我正在尝试创建一个能够删除列表中项目的点击事件,但是当我点击它时,我得到了 "TypeError: Cannot read property 'props' of undefined"。
我尽量坚持使用 ES6,我很确定它可以在某处绑定 'this',但我尝试了很多地方,但都没有成功。
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<StreetFighter />
</div>
);
}
}
class StreetFighter extends Component {
constructor(props) {
super(props);
this.state = {
characters: [
'Chun-Li',
'Guile',
'Ryu',
'Ken',
'E.Honda',
'Dhalsim',
],
};
}
render() {
let characters = this.state.characters;
characters = characters.map((char, index) => {
return (
<Character char={char} key={index} onDelete={this.onDelete} />
);
});
return (
<div>
<p>Street Fighter Characters</p>
<ul>{characters}</ul>
</div>
);
}
onDelete(chosenCharacter) {
let updatedCharactersList = this.state.characters.filter(
(char, index) => {
return chosenCharacter !== char;
}
);
this.setState({
characters: updatedCharactersList,
});
}
}
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete}
> x </span>
</div>
</li>
)
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
export default App;
由于 JS OOP 系统,当您将 class 方法传递给 props 时,您重写了它的上下文。因此,要使其发挥作用,有几种方法:
1) 这不太好,因为总是绑定 returns 新函数,即使 props
中没有更新,你的组件也会重新渲染
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<StreetFighter />
</div>
);
}
}
class StreetFighter extends Component {
constructor(props) {
super(props);
this.state = {
characters: [
'Chun-Li',
'Guile',
'Ryu',
'Ken',
'E.Honda',
'Dhalsim',
],
};
}
render() {
let characters = this.state.characters;
characters = characters.map((char, index) => {
return (
<Character char={char} key={index} onDelete={this.onDelete.bind(this)} />
);
});
return (
<div>
<p>Street Fighter Characters</p>
<ul>{characters}</ul>
</div>
);
}
onDelete(chosenCharacter) {
let updatedCharactersList = this.state.characters.filter(
(char, index) => {
return chosenCharacter !== char;
}
);
this.setState({
characters: updatedCharactersList,
});
}
}
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete.bind(this)}
> x </span>
</div>
</li>
)
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
export default App;
2) 在我的代码中,我使用箭头函数作为这种情况的 class 属性(我认为这是最常见的解决方案之一)
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete}
> x </span>
</div>
</li>
)
};
handleDelete = () => {
this.props.onDelete(this.props.char);
}
}
通过使用箭头函数,可以解决this
上下文。试试这个:
你的 onClick 事件
onClick={this.handleDelete}
和您的函数定义:
handleDelete = () => {
//here you can access the this.props
}
当您在 handleDelete
中使用 this
时,您没有引用 class。您可以使用以下方法解决此问题
使用无状态组件(适合您的情况的最佳方法)
不改变状态的组件,不需要Class
,你可以将它们定义为函数或常量
Class Parent extends React.Component {
state = { ... }
onDelete = () => { ... }
render() {
return (
<Child onDelete={this.onDelete} />
)
}
}
function Child(props) {
return (
<button onClick={props.onDelete}>Delete</button>
)
}
使用箭头函数
箭头函数不定义作用域,在箭头函数内部你在 class 作用域中。
Class Parent extends React.Component {
state = { foo: 'bar' }
wrongMethod() {
console.log(this.state) // undefined
}
rightMethod = () => {
console.log(this.state) // { foo: 'bar' }
}
render() {
this.wrongMethod()
this.rightMethod()
return (
<h1>Hello World!</h1>
)
}
}
使用绑定
如果您有一个使用 this
的方法,您必须将方法作用域绑定到 class 作用域,这可以像下面那样进行。 bindOnRender
由于在每次渲染时调用并在每次调用时创建新函数而存在性能问题。
Class Parent extends React.Component {
constructor() {
this.state = { foo: 'bar' }
this.bindOnConstructor.bind(this)
}
bindOnConstructor() {
console.log(this.state) // { foo: 'bar' }
}
bindOnRender = () => {
console.log(this.state) // { foo: 'bar' }
}
render() {
return (
<button onClick={this.bindOnConstructor}>Foo</button>
<button onClick={this.bindOnRender.bind(this)}>Bar</button>
)
}
}
TLDR:您的代码中的具体问题已在该答案末尾的段落中说明。
这是 Java 脚本 this
的一个 class 逻辑问题,如果您还没有读过,我建议您稍微读一下。
简而言之(不只是为了你,如果其他人正在阅读这篇文章),Java脚本函数定义(如果没有写成 arrow function)重新定义this
是什么,即它指向什么。
所以当你定义它时:
handleDelete() {
this.props.onDelete(this.props.char);
}
该函数的 this
未指向其中定义的 class 的对象实例。如果您来自 C++/C#/Java背景。问题是 this
在 classes 进入 JavaScript 之前就退出了,而 classes 注意到的不仅仅是具有一堆已定义原型的函数的语法糖(参见 here),或者换句话说,默认情况下它不会将 this 绑定到它的函数。
有几种典型的解决方法:
将this
绑定到所有函数(在构造函数中)
class Character extends Component {
constructor(props) {
super(props)
this.handleDelete = this.handleDelete.bind(this)
}
render() {
// ...
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
注意: 您可以在每次使用函数 时绑定 this
而不是这个 (即 onClick={this.handleDelete.bind(this)}
,但不可取,因为如果您忘记绑定 this
,它会使您的代码容易出错。此外,如果您正在链接函数,您可能会指出在某处错误的事情。更不用说 bind
是一个函数,在 React 中你将在每个渲染器上进行函数调用。但是,记住 if 是一件好事您曾经遇到过必须更改 this
.
的情况
使用箭头函数
class Character extends Component {
render() {
// ...
};
handleDelete = () => {
this.props.onDelete(this.props.char);
}
}
如上所述,在其他答案中,箭头函数不会重新定义 this
指针。您在这里有效地做的是将箭头函数分配给此 class 的对象实例的属性。换句话说,该函数(作为不重新定义 this
的箭头函数)从外部范围(class 的范围)获取 this
,但是,因为箭头函数是匿名的函数,您通过将其分配给 name property.
来命名它
所有其他解决方案都是以上两个的一些变体
关于您的解决方案
onDelete
和 handleDelete
都遇到了 this
问题。
此外,如 @Alyson Maia has stated above, your Character
component can be written as a functional component:
const Character = (props) => {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={props.onDelete(props.char)}
> x </span>
</div>
</li>
)
};
}
当你创建一个函数来处理一个事件时,不要忘记通过构造函数将它添加到你的道具中,如下所示:
constructor (props) {
super(props)
this.yourFunction = this.yourFunction.bind(this)
}
我正在尝试创建一个能够删除列表中项目的点击事件,但是当我点击它时,我得到了 "TypeError: Cannot read property 'props' of undefined"。
我尽量坚持使用 ES6,我很确定它可以在某处绑定 'this',但我尝试了很多地方,但都没有成功。
import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<StreetFighter />
</div>
);
}
}
class StreetFighter extends Component {
constructor(props) {
super(props);
this.state = {
characters: [
'Chun-Li',
'Guile',
'Ryu',
'Ken',
'E.Honda',
'Dhalsim',
],
};
}
render() {
let characters = this.state.characters;
characters = characters.map((char, index) => {
return (
<Character char={char} key={index} onDelete={this.onDelete} />
);
});
return (
<div>
<p>Street Fighter Characters</p>
<ul>{characters}</ul>
</div>
);
}
onDelete(chosenCharacter) {
let updatedCharactersList = this.state.characters.filter(
(char, index) => {
return chosenCharacter !== char;
}
);
this.setState({
characters: updatedCharactersList,
});
}
}
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete}
> x </span>
</div>
</li>
)
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
export default App;
由于 JS OOP 系统,当您将 class 方法传递给 props 时,您重写了它的上下文。因此,要使其发挥作用,有几种方法:
1) 这不太好,因为总是绑定 returns 新函数,即使 props
中没有更新,你的组件也会重新渲染import React, { Component } from 'react';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<StreetFighter />
</div>
);
}
}
class StreetFighter extends Component {
constructor(props) {
super(props);
this.state = {
characters: [
'Chun-Li',
'Guile',
'Ryu',
'Ken',
'E.Honda',
'Dhalsim',
],
};
}
render() {
let characters = this.state.characters;
characters = characters.map((char, index) => {
return (
<Character char={char} key={index} onDelete={this.onDelete.bind(this)} />
);
});
return (
<div>
<p>Street Fighter Characters</p>
<ul>{characters}</ul>
</div>
);
}
onDelete(chosenCharacter) {
let updatedCharactersList = this.state.characters.filter(
(char, index) => {
return chosenCharacter !== char;
}
);
this.setState({
characters: updatedCharactersList,
});
}
}
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete.bind(this)}
> x </span>
</div>
</li>
)
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
export default App;
2) 在我的代码中,我使用箭头函数作为这种情况的 class 属性(我认为这是最常见的解决方案之一)
class Character extends Component {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={this.handleDelete}
> x </span>
</div>
</li>
)
};
handleDelete = () => {
this.props.onDelete(this.props.char);
}
}
通过使用箭头函数,可以解决this
上下文。试试这个:
你的 onClick 事件
onClick={this.handleDelete}
和您的函数定义:
handleDelete = () => {
//here you can access the this.props
}
当您在 handleDelete
中使用 this
时,您没有引用 class。您可以使用以下方法解决此问题
使用无状态组件(适合您的情况的最佳方法)
不改变状态的组件,不需要Class
,你可以将它们定义为函数或常量
Class Parent extends React.Component {
state = { ... }
onDelete = () => { ... }
render() {
return (
<Child onDelete={this.onDelete} />
)
}
}
function Child(props) {
return (
<button onClick={props.onDelete}>Delete</button>
)
}
使用箭头函数
箭头函数不定义作用域,在箭头函数内部你在 class 作用域中。
Class Parent extends React.Component {
state = { foo: 'bar' }
wrongMethod() {
console.log(this.state) // undefined
}
rightMethod = () => {
console.log(this.state) // { foo: 'bar' }
}
render() {
this.wrongMethod()
this.rightMethod()
return (
<h1>Hello World!</h1>
)
}
}
使用绑定
如果您有一个使用 this
的方法,您必须将方法作用域绑定到 class 作用域,这可以像下面那样进行。 bindOnRender
由于在每次渲染时调用并在每次调用时创建新函数而存在性能问题。
Class Parent extends React.Component {
constructor() {
this.state = { foo: 'bar' }
this.bindOnConstructor.bind(this)
}
bindOnConstructor() {
console.log(this.state) // { foo: 'bar' }
}
bindOnRender = () => {
console.log(this.state) // { foo: 'bar' }
}
render() {
return (
<button onClick={this.bindOnConstructor}>Foo</button>
<button onClick={this.bindOnRender.bind(this)}>Bar</button>
)
}
}
TLDR:您的代码中的具体问题已在该答案末尾的段落中说明。
这是 Java 脚本 this
的一个 class 逻辑问题,如果您还没有读过,我建议您稍微读一下。
简而言之(不只是为了你,如果其他人正在阅读这篇文章),Java脚本函数定义(如果没有写成 arrow function)重新定义this
是什么,即它指向什么。
所以当你定义它时:
handleDelete() {
this.props.onDelete(this.props.char);
}
该函数的 this
未指向其中定义的 class 的对象实例。如果您来自 C++/C#/Java背景。问题是 this
在 classes 进入 JavaScript 之前就退出了,而 classes 注意到的不仅仅是具有一堆已定义原型的函数的语法糖(参见 here),或者换句话说,默认情况下它不会将 this 绑定到它的函数。
有几种典型的解决方法:
将this
绑定到所有函数(在构造函数中)
class Character extends Component {
constructor(props) {
super(props)
this.handleDelete = this.handleDelete.bind(this)
}
render() {
// ...
};
handleDelete() {
this.props.onDelete(this.props.char);
}
}
注意: 您可以在每次使用函数 时绑定 this
而不是这个 (即 onClick={this.handleDelete.bind(this)}
,但不可取,因为如果您忘记绑定 this
,它会使您的代码容易出错。此外,如果您正在链接函数,您可能会指出在某处错误的事情。更不用说 bind
是一个函数,在 React 中你将在每个渲染器上进行函数调用。但是,记住 if 是一件好事您曾经遇到过必须更改 this
.
使用箭头函数
class Character extends Component {
render() {
// ...
};
handleDelete = () => {
this.props.onDelete(this.props.char);
}
}
如上所述,在其他答案中,箭头函数不会重新定义 this
指针。您在这里有效地做的是将箭头函数分配给此 class 的对象实例的属性。换句话说,该函数(作为不重新定义 this
的箭头函数)从外部范围(class 的范围)获取 this
,但是,因为箭头函数是匿名的函数,您通过将其分配给 name property.
所有其他解决方案都是以上两个的一些变体
关于您的解决方案
onDelete
和 handleDelete
都遇到了 this
问题。
此外,如 @Alyson Maia has stated above, your Character
component can be written as a functional component:
const Character = (props) => {
render() {
return (
<li>
<div className="character">
<span className="character-name">{this.props.char}</span>
<span
className="character-delete"
onClick={props.onDelete(props.char)}
> x </span>
</div>
</li>
)
};
}
当你创建一个函数来处理一个事件时,不要忘记通过构造函数将它添加到你的道具中,如下所示:
constructor (props) {
super(props)
this.yourFunction = this.yourFunction.bind(this)
}