Обработчик событий React работает без bind () - PullRequest
1 голос
/ 27 марта 2019

Я работаю над учебником по реагированию, и инструктор показывает, что обработчик событий в этом коде не будет работать, потому что 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;

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

Как говорит Афзал Хоссейн , вы вызываете this.handleIncrement() при рендеринге элемента, а не при нажатии кнопки.

Вам необходимо предоставить сам дескриптор функции для onClick и bind() для правильного контекста при его создании, чтобы this всегда обращался к экземпляр 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'));
<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/>
0 голосов
/ 27 марта 2019

Любая функция, вызываемая напрямую из метода рендеринга, получит объект контейнера как this Но когда мы назначаем функцию событию onClick, мы не хотим немедленно вызывать эту функцию ...поэтому мы присваиваем его так:

<button onClick={this.handleIncrement}>

(только имя функции без () в конце) ... и это говорит о вызове функции при нажатии кнопки.

Но когда вы нажимаете кнопку, функция больше не будет вызываться из метода render, поэтому ссылка this будет изменена и приведет к ошибке.

В вашем случае вы добавили () кваша this.handleIncrement функция вызывает ее немедленно ... так что она не вызывает никаких проблем, но она даст вам неправильные результаты почти во всех случаях, так как она не будет вызываться на click, но будет вызываться с каждым рендером.

Поскольку ваш простой код отображается только при нажатии кнопки, это, вероятно, решает проблему. Добавьте вторую кнопку , и она даст неправильный результат, или пользовательский интерфейс замерзнет.

Правильный способ - удалить () после this.handleIncreament и связать функцию внутри конструктор ... this.handleIncreament = this.handleIncreament.bind(this)

...