反应事件处理程序无需bind()

时间:2019-03-27 14:04:52

标签: reactjs event-handling bind

我正在阅读一个React教程,并且讲师正在显示此代码中的事件处理程序将不起作用,因为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;

5 个答案:

答案 0 :(得分:1)

问题是,当您的事件处理程序需要从本地范围访问this时,您调用了这样的方法; this.handleClick(),您要告诉JavaScript实现方法的任务,即立即到达该方法(在您的情况下,立即将其呈现),通常不需要绑定到this

但是当您“调用”(我将其引号,因为正确的单词应为REFER)时,是这样的方法; this.handleClick,您实际上是在指该方法(意味着仅当用户执行某些操作时才应调用该方法),而不是立即调用它。这需要绑定this.handleClick= this.handleClick.bind(this);或对方法handleClick = () => {};使用箭头功能。它主要用于onClick功能。

您没有在代码中得到该错误,因为您包括了括号-this.handleIncrement()。如果您删除括号并在consoleLog中仍this.state handleIncrement,肯定会出现undefined错误。但是,如果您的handleIncrement仅记录了状态以外的内容,则不会收到错误消息。

如果您了解我的基本解释,请接受答案。

答案 1 :(得分:0)

从render方法直接调用 的任何函数都将获取容器对象为this 但是,当我们将函数分配给onClick事件时,我们不想立即调用该函数...所以我们这样分配它

<button onClick={this.handleIncrement}>

(仅末尾没有()的函数名)...这表示单击按钮时调用该函数。

但是,当您单击按钮时,将不再从render方法中调用该函数,因此this引用将被更改并产生错误。

在您的情况下,您将()添加到了this.handleIncrement函数中,因此立即调用了它……因此它不会引起任何问题,但是在几乎所有情况下,由于它不会给您带来错误的结果,不会在click上被调用,但是它将在每次渲染时被调用。

由于您的简单代码仅在单击按钮时呈现,因此可能可以解决问题。 添加第二个按钮,它将给出错误的结果,或者UI冻结。

正确的方法是删除()之后的this.handleIncreament并将函数绑定到构造函数 ... this.handleIncreament = this.handleIncreament.bind(this)

答案 2 :(得分:0)

正如Afzal Hossain所说,您是在渲染元素时而不是单击按钮时调用this.handleIncrement()

您需要向onClick提供函数句柄,并在构造函数时将其bind()置于正确的上下文中,以便this始终访问{{1}的实例}在Counter中。

以下是他在回答中提出的建议的有效实施方式:

handleIncrement()
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'));

答案 3 :(得分:0)

如果没有bind()方法,则可以在handleincrement中直接使用箭头功能。 检查以下代码

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/>

答案 4 :(得分:0)

我同意Afzal Hossain

<button onClick={this.handleIncrement()}>

此行将在渲染时调用 handleIncrement 函数。这不是添加事件的正确方法。

<button onClick={this.handleIncrement}>

这将是调用函数的正确方法。但由于它是一个回调,它不会知道 this 是什么,因为它不在同一个上下文中。

React Documentation 非常清楚为什么我们应该始终将回调函数与 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;

有关详细信息,请参阅此 documentation 链接。