Обработчики событий
Связывание обработчиков событий в конструкторе.
В большинстве случаев мы обрабатываем события DOM в компоненте, который содержит элементы, отправляющие события. Как и в примере ниже, у нас есть обработчик кликов, и мы хотим запустить функцию или метод одного и того же компонента:
class Switcher extends React.Component {
render() {
return (
<button onClick={ this._handleButtonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log('Button is clicked');
}
}
Все отлично, потому что_handleButtonClick
- это функция, и мы действительно передаем функцию атрибуту onClick
. Проблема в том, что этот код не сохраняет контекст. Итак, если мы захотим использовать this
внутри _handleButtonClick
, то получим ошибку.
class Switcher extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'React in patterns' };
}
render() {
return (
<button onClick={ this._handleButtonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log(`Button is clicked inside ${ this.state.name }`);
// Приводит к
// Uncaught TypeError: Cannot read property 'state' of null
}
}
Обычно мы используем bind:
<button onClick={ this._handleButtonClick.bind(this) }>
click me
</button>
Однако это означает, что функция bind вызывается снова и снова, потому что мы можем отображать кнопку много раз. Лучшим подходом была бы передача bind в конструкторе компонента:
class Switcher extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'React in patterns' };
this._buttonClick = this._handleButtonClick.bind(this);
}
render() {
return (
<button onClick={ this._buttonClick }>
click me
</button>
);
}
_handleButtonClick() {
console.log(`Button is clicked inside ${ this.state.name }`);
}
}
Другой альтернативой является использование стрелочный функций для onClick
. Стрелочные функции не влияют на контекст во время вызова ( значение this
используется в окружении).
Facebook, кстати, рекомендует тот же метод при работе с функциями, который нуждаеться в контексте одного и того же компонента. Связывание в конструкторе может быть полезно, если мы передаем обратные вызовы по дереву.
Короткий пример с использованием стрелочных функций:
class Switcher extends React.Component {
state = { name: 'React in patterns' };
render() {
return (
<button onClick={ this._handleButtonClick }>
click me
</button>
);
}
_handleButtonClick = () => {
console.log(`Button is clicked inside ${ this.state.name }`);
}
}