React class 组件在方法上异常绑定
React class component unusual this binding on methods
例如下面的 class 组件:
class Todo extends Component {
state = {
list: ["First Todo"],
text: ""
};
handleSubmit(e) {
e.preventDefault();
if (this && this.setState) {
console.log("this present in handleSubmit");
this.setState(prevState => ({
list: prevState.list.concat(this.state.text),
text: ""
}));
} else {
console.log("this not present in handleSubmit");
}
}
handleChange(e) {
if (this && this.setState) {
console.log("this present in handleChange");
this.setState({
text: e.target.value
});
} else {
console.log("this not present in handleChange");
}
}
removeItem(index) {
if (!this || !this.setState) {
console.log("this not present in removeItem");
}
console.log("this present in removeItem");
const list = this.state.list;
list.splice(index, 1);
this.setState({ list });
}
render() {
return (
<div>
<h1>TODO LIST</h1>
<form onSubmit={this.handleSubmit}>
<input value={this.state.text} onChange={e => this.handleChange(e)} />
<button>Add</button>
<ol>
{this.state.list.map((item, index) => {
return (
<li key={index}>
{item}
<button onClick={() => this.removeItem(index)}>Delete</button>
</li>
);
})}
</ol>
</form>
</div>
);
}
}
this
绑定到 class 方法的行为不一致。
使用组件我们会发现,handleChange
和 removeItem
具有正确的 this
上下文,而 handleSubmit
具有 this
上下文undefined
.
两个具有正确 this
上下文的函数在 jsx 中表示为箭头函数。如下所示:
<input value={this.state.text} onChange={e => this.handleChange(e)} />
而 handleSubmit
作为函数本身传递。如下所示:
<form onSubmit={this.handleSubmit}>
但是,我真的不知道为什么会这样。因为,根据我的理解,函数的传递方式应该无关紧要,即作为函数本身或上面的箭头表示。
箭头函数有词法 this
。这意味着 its value is determined by the surrounding scope。因此,当您使用它而不是 class methods
时,this
值将映射到实例。但是当您调用 this.onSubmit
时,this
将引用本地范围而不是实例本身。要解决它,请使用 arrow functions
或 bind
构造函数中的 onSubmit
方法。
constructor(props){
super(props)
this.onSubmit = this.onSubmit.bind(this)
}
In my understanding, it should not have mattered how the function was passed...
所以这里有新东西要学
传递 onChange={e => this.handleChange(e)}
与在构造函数中使用 .bind
或传递引用并使用 .bind
.
相同
在 render 方法中将其作为箭头函数传递时,它将获取组件的 this
而不是方法的 this。
您应该注意到 onChange={e => this.handleChange(e)}
不是一个好的做法,因为在每次渲染时您都会创建一个新函数。
例如下面的 class 组件:
class Todo extends Component {
state = {
list: ["First Todo"],
text: ""
};
handleSubmit(e) {
e.preventDefault();
if (this && this.setState) {
console.log("this present in handleSubmit");
this.setState(prevState => ({
list: prevState.list.concat(this.state.text),
text: ""
}));
} else {
console.log("this not present in handleSubmit");
}
}
handleChange(e) {
if (this && this.setState) {
console.log("this present in handleChange");
this.setState({
text: e.target.value
});
} else {
console.log("this not present in handleChange");
}
}
removeItem(index) {
if (!this || !this.setState) {
console.log("this not present in removeItem");
}
console.log("this present in removeItem");
const list = this.state.list;
list.splice(index, 1);
this.setState({ list });
}
render() {
return (
<div>
<h1>TODO LIST</h1>
<form onSubmit={this.handleSubmit}>
<input value={this.state.text} onChange={e => this.handleChange(e)} />
<button>Add</button>
<ol>
{this.state.list.map((item, index) => {
return (
<li key={index}>
{item}
<button onClick={() => this.removeItem(index)}>Delete</button>
</li>
);
})}
</ol>
</form>
</div>
);
}
}
this
绑定到 class 方法的行为不一致。
使用组件我们会发现,handleChange
和 removeItem
具有正确的 this
上下文,而 handleSubmit
具有 this
上下文undefined
.
两个具有正确 this
上下文的函数在 jsx 中表示为箭头函数。如下所示:
<input value={this.state.text} onChange={e => this.handleChange(e)} />
而 handleSubmit
作为函数本身传递。如下所示:
<form onSubmit={this.handleSubmit}>
但是,我真的不知道为什么会这样。因为,根据我的理解,函数的传递方式应该无关紧要,即作为函数本身或上面的箭头表示。
箭头函数有词法 this
。这意味着 its value is determined by the surrounding scope。因此,当您使用它而不是 class methods
时,this
值将映射到实例。但是当您调用 this.onSubmit
时,this
将引用本地范围而不是实例本身。要解决它,请使用 arrow functions
或 bind
构造函数中的 onSubmit
方法。
constructor(props){
super(props)
this.onSubmit = this.onSubmit.bind(this)
}
In my understanding, it should not have mattered how the function was passed...
所以这里有新东西要学
传递 onChange={e => this.handleChange(e)}
与在构造函数中使用 .bind
或传递引用并使用 .bind
.
在 render 方法中将其作为箭头函数传递时,它将获取组件的 this
而不是方法的 this。
您应该注意到 onChange={e => this.handleChange(e)}
不是一个好的做法,因为在每次渲染时您都会创建一个新函数。