We want to hear from you!Take our 2021 Community Survey!
This site is no longer updated.Go to react.dev

Обробка подій

These docs are old and won’t be updated. Go to react.dev for the new React docs.

These new documentation pages teach modern React and include live examples:

Обробка подій для React-елементів дуже схожа до обробки подій для DOM-елементів. Але є деякі синтаксичні відмінності:

  • Події React іменуються в camelCase, а не в нижньому регістрі.
  • З JSX ви передаєте функцію як обробник події замість рядка.

Наприклад, HTML:

<button onclick="activateLasers()">
  Активувати лазери
</button>

дещо відрізняється в React:

<button onClick={activateLasers}>  Активувати лазери
</button>

Інша відмінність полягає в тому, що ви не можете повернути false для того, щоб запобігти поведінці за замовчуванням у React. Ви маєте явно викликати preventDefault. Наприклад, для звичайного HTML, щоб запобігти поведінці посилання за замовчуванням (відкриття нової сторінки) ви можете написати:

<form onsubmit="console.log('You clicked submit.'); return false">
  <button type="submit">Submit</button>
</form>

У React це може виглядати так:

function Form() {
  function handleSubmit(e) {
    e.preventDefault();    console.log('You clicked submit.');
  }

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">Submit</button>
    </form>
  );
}

Тут e - це синтетична подія. React визначає ці синтетичні події відповідно до специфікації W3C, тому вам не потрібно турбуватися про сумісніть між браузерами. React-події працюють інакше, ніж нативні події. Перегляньте довідник по SyntheticEvent, щоб дізнатися більше.

Зазвичай, коли ви використовуєте React, вам не потрібно викликати addEventListener, щоб додати обробник до DOM-елементу після його створення. Натомість, просто вкажіть обробник, коли елемент вперше відрендерився.

Коли ви визначаєте компонент як клас ES6, поширеною практикою є оголошення обробника подій як методу цього класу. Наприклад, цей Toggle компонент рендерить кнопку, котра дозволяє користувачу перемикатись між станами “ON” і “OFF”:

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // Ця прив'язка необхідна, щоб `this` працював у функції зворотнього виклику    this.handleClick = this.handleClick.bind(this);  }

  handleClick() {    this.setState(prevState => ({      isToggleOn: !prevState.isToggleOn    }));  }
  render() {
    return (
      <button onClick={this.handleClick}>        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

Спробуйте на CodePen

Ви маєте бути обережним із значенням this у JSX функціях зворотнього виклику. У JavaScript класові методи за замовчуванням не зв’язані. Якщо ви забудете зв’язати this.handleClick і передати її до onClick, this буде undefined під час виклику функції.

Така поведінка не є особливою лише для React - вона є частиною того, як функції працюють в JavaScript. В загальному випадку, якщо ви посилаєтесь на метод без () після нього, як наприклад onClick={this.handleClick}, ви маєте зв’язати цей метод.

Якщо виклики bind дратують вас - є два шляхи обійти їх. Якщо ви використовуєте експериментальний синтаксис відкритих полей класу, то ви можете використовувати поля класу, щоб правильно прив’язувати функції зворотнього виклику:

class LoggingButton extends React.Component {
  // Цей синтаксис забезпечує прив'язку `this` всередині handleClick.  handleClick = () => {    console.log('this це:', this);  };  render() {
    return (
      <button onClick={this.handleClick}>
        Натисни на мене
      </button>
    );
  }
}

За замовчуванням, цей синтаксис включено до Create React App.

Якщо ви не використовуєте синтаксис полей класу, ви можете використати стрілкову функцію в функції зворотнього виклику:

class LoggingButton extends React.Component {
  handleClick() {
    console.log('this це:', this);
  }

  render() {
    // Цей синтаксис забезпечує прив'язку `this` всередині handleClick.    return (      <button onClick={() => this.handleClick()}>        Натисни на мене
      </button>
    );
  }
}

Проблема цього синтаксису полягає в тому, що при кожному рендері LoggingButton створюється нова функція зворотнього виклику. У більшості випадків це не створює додаткових проблем. Але, якщо ця функція зворотнього виклику передається в якості пропcу в компоненти нижче - вони можуть здійснити додатковий ререндеринг. Як правило, ми рекомендуємо зв’язувати в конструкторі або використувати синтаксис полей класу, щоб уникнути подібних проблем з продуктивністю.

Передача аргументів до обробників подій

Всередині циклу доволі часто потрібно передати додатковий параметр до обробника події. Наприклад, якщо id це ID рядка, можна застосувати один з нижченаведених прикладів:

<button onClick={(e) => this.deleteRow(id, e)}>Видалити рядок</button>
<button onClick={this.deleteRow.bind(this, id)}>Видалити рядок</button>

Обидва приклади є еквівалентними і використовують стрілкові функції та Function.prototype.bind відповідно.

В обох випадках аргумент e, який відповідає події React, буде переданий другим аргументом після ID. Для стрілкової функції ми маємо зробити передачу явною, але для bind будь-які наступні аргументи будуть передані автоматично.