我正在学习一个反应教程,讲师表明此代码中的事件处理程序不起作用,因为 this() 正在访问外部环境。但我没有得到错误。有人可以向我解释一下吗?
import React, { Component } from "react";
class Counter extends Component {
state = {
count: 0,
};
handleIncrement() {
console.log(this.state);
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.handleIncrement()}>
Increment
</button>
</div>
);
}
}
export default Counter;
问题是,当您的事件处理程序需要从本地范围访问this
时,您可以像这样调用该方法;this.handleClick()
,您告诉 JavaScript 立即实现方法的任务(在您的情况下,它立即被渲染),这通常不需要绑定到this
.
但是当你"调用"(我把它放在引号里,因为正确的词应该是 REFER)这样的方法;this.handleClick
,您实际上指的是该方法(意味着只有在用户执行某些操作时才应调用它),而不是立即调用它。这要么需要绑定this.handleClick= this.handleClick.bind(this);
,要么需要对方法handleClick = () => {};
使用箭头函数。它主要用于onClick
功能。
您在代码中没有收到该错误,因为您包含括号 -this.handleIncrement()
。如果您删除括号并且仍然consoleLog
this.state
handleIncrement
,您肯定会得到undefined
错误。但是,如果您的handleIncrement
仅记录状态之外的内容,则不会收到错误。
如果您理解我的基本解释,请接受答案。
直接从render 方法调用的任何函数都将获取容器对象this
但是当我们onClick
事件分配一个函数时,我们不想立即调用该函数......所以我们像这样分配它
<button onClick={this.handleIncrement}>
(只有函数名称,末尾没有()
)...这表示在单击按钮时调用该函数。
但是,当您单击该按钮时,将不再从render
方法调用该函数,因此this
引用将被更改并产生错误。
在您的情况下,您将()
添加到this.handleIncrement
函数中,并立即调用它......所以它不会引起任何问题,但它会在几乎所有情况下给你错误的结果,因为它不会被调用click
但它会在每次渲染时被调用。
由于您的简单代码仅在单击按钮时呈现,因此可能会纠正问题。添加第二个按钮,它将给出错误的结果或 UI 将冻结。
正确的方法是在this.handleIncreament
后删除()
并将函数绑定在构造函数中......this.handleIncreament = this.handleIncreament.bind(this)
如果没有 bind() 方法,您可以在句柄增量中使用直接箭头函数。 检查下面的代码
const { Component } = React;
class Counter extends Component {
state = { count: 0 };
handleIncrement=()=> {
const { count } = this.state;
this.setState({ count: count + 1 });
}
render () {
return <label>
<div>Count {this.state.count}</div>
<button onClick={this.handleIncrement}>Increment</button>
</label>;
}
}
ReactDOM.render(<Counter/>, document.querySelector('main'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main/>
我同意Afzal Hossain的观点。
<button onClick={this.handleIncrement()}>
此行将在渲染时调用handleIncrement
函数。这不是添加事件的正确方法。
<button onClick={this.handleIncrement}>
这将是调用函数的正确方法。但是由于它是一个回调,它不知道this
是什么,因为它不在同一上下文中。
React 文档非常清楚地说明了为什么我们应该始终将回调函数与this
绑定,以使上下文在该特定函数中可用。
但是,如果您不想绑定函数,则 react 文档中提到了两种解决方法
公共类字段语法
import React, { Component } from "react";
class Counter extends Component {
state = {
count: 0,
};
handleIncrement = () => {
console.log(this.state);
console.log(this.props);
}
render() {
return (
<div>
<button onClick={this.handleIncrement}>
Increment
</button>
</div>
);
}
}
export default Counter;
ReactDOM.render(<Counter/>, document.querySelector('main'));
箭头函数
import React, { Component } from "react";
class Counter extends Component {
state = {
count: 0,
};
handleIncrement() {
console.log(this.state);
console.log(this.props);
}
render() {
return (
<div>
<button onClick={() => this.handleIncrement()}>
Increment
</button>
</div>
);
}
}
export default Counter;
有关更多详细信息,请参阅此文档链接。
正如Afzal Hossain所说,你在元素呈现时调用this.handleIncrement()
,而不是在单击按钮时调用。
你需要提供函数句柄本身来onClick
,并在构造时将其bind()
到正确的上下文中,以便this
始终访问handleIncrement()
中的Counter
实例。
以下是他在回答中提出的建议的工作实施:
const { Component } = React;
class Counter extends Component {
state = { count: 0 };
handleIncrement = this.handleIncrement.bind(this);
handleIncrement () {
const { count } = this.state;
this.setState({ count: count + 1 });
}
render () {
return <label>
<div>Count {this.state.count}</div>
<button onClick={this.handleIncrement}>Increment</button>
</label>;
}
}
ReactDOM.render(<Counter/>, document.querySelector('main'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<main/>