Обробка подій
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>
);
}
}
Ви маєте бути обережним із значенням 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
будь-які наступні аргументи будуть передані автоматично.