React 事件处理程序在没有 bind() 的情况下工作



我正在学习一个反应教程,讲师表明此代码中的事件处理程序不起作用,因为 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()。如果您删除括号并且仍然consoleLogthis.statehandleIncrement,您肯定会得到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/>

相关内容

  • 没有找到相关文章