Обработка событий
Обработка событий с помощью React-элементов очень похожа на обработку событий на элементах DOM. Есть некоторые различия в синтаксисе:
- React-события имеют имена с использованием camelCase, а не строчных букв.
- С помощью JSX в качестве обработчика события передается функция, а не строка.
Например, HTML:
<button onclick="activateLasers()"> Activate Lasers </button>
несколько отличается в React:
<button onClick={activateLasers}>
Activate Lasers
</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 W3C spec, поэтому вам не нужно беспокоиться о кроссбраузерной совместимости. React-события работают не совсем так же, как родные события. См. справочник SyntheticEvent, чтобы узнать больше.
При использовании React, как правило, нет необходимости вызывать addEventListener для добавления слушателей к элементу DOM после его создания. Вместо этого просто укажите слушателя при первоначальном отрисовке элемента.
При определении компонента с помощью класса ES6, распространённой практикой является использование обработчика события как метода класса. Например, этот Toggle компонент отображает кнопку, которая позволяет пользователю переключаться между состояниями «ВКЛ» и «ВЫКЛ»:
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
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>
);
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
); Необходимо быть внимательным к значению this в JSX-обработчиках. В JavaScript методы класса по умолчанию не привязаны. Если вы забудете привязать this.handleClick и передадите его в onClick, this будет undefined при фактическом вызове функции.
Это не поведение, специфичное для React; это часть того, как работают функции в JavaScript. Как правило, если вы ссылаетесь на метод без () после него, например, onClick={this.handleClick}, вы должны привязать этот метод.
Если вызывать bind вас раздражает, есть два способа обойти эту проблему. Если вы используете экспериментальный синтаксис общедоступных свойств класса, вы можете использовать свойства класса для правильной привязки обработчиков:
class LoggingButton extends React.Component {
// This syntax ensures `this` is bound within handleClick.
// Warning: this is *experimental* syntax.
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
} Этот синтаксис включён по умолчанию в Create React App.
Если вы не используете синтаксис свойств класса, вы можете использовать стрелочную функцию в обработчике:
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// This syntax ensures `this` is bound within handleClick
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
} Проблема с этим синтаксисом заключается в том, что каждый раз при отрисовке LoggingButton создается другой обработчик. В большинстве случаев это нормально. Однако, если этот обработчик передаётся в качестве свойства компонентам нижнего уровня, эти компоненты могут выполнить дополнительное перерисовывание. В целом, мы рекомендуем привязку в конструкторе или использование синтаксиса свойств класса, чтобы избежать подобных проблем с производительностью.
Передача аргументов обработчикам событий
В цикле часто необходимо передать дополнительный параметр обработчику события. Например, если id — это идентификатор строки, то любой из следующих вариантов сработает:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button> Вышеуказанные две строки эквивалентны и используют стрелочные функции и Function.prototype.bind соответственно.
В обоих случаях, аргумент e, представляющий React-событие, будет передан как второй аргумент после идентификатора. При использовании стрелочной функции мы должны передать его явно, но с bind все последующие аргументы автоматически передаются.
© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://17.reactjs.org/docs/handling-events.html