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