Вы передаете метод
clickHandle в колбек слушателя события
click, при вызове метод теряет контекст, так как вызывается не на вашем объекте.
this в таком случае ссылается не на ваш объект, а на
undefined. Так как
babel при трансляции добавляет
'use strict' (иначе, при выполнении в браузере, ссылался бы на
window). Исправить это можно несколькими способами:
1. переделать обработчик из метода класса в
class field arrow function:
было:
clickHandle(e) {
// some code
}
стало:
clickHandle = e => {
// some code
};
class field arrow function получает контекстом экземпляр класса при инициализации и всегда ссылается на него, куда бы вы ее не передали. Это
экспериментальная возможность JavaScript и в спецификации ее пока нет. За трансляцию этой конструкции в валидный код отвечает
babel.
Результат, который будет получен после трансляции, можно посмотреть
тут. Строки с 23 по 28.
2.забиндить его в конструкторе на экземпляр класса:
constructor(props) {
super(props);
this.clickHandle = this.clickHandle.bind(this);
}
Вызов
bind возвращает обертку, которая вызывает ваш метод, испльзуя переданный аргумент как контекст, в нашем случае это экземпляр класса.
3. обернуть в стрелочную функцию в
render:
<SomeComponent onClick={() => this.сlickHandle()} /> // контекст не будет потерян
При оборачивании в стрелочную функцию происходит следующее: сама функция использует как контекст ваш объект, поэтому при вызове метод будет вызван на вашем объекте и
this в самом методе будет ссылаться на объект. Этот вариант разумно использовать, только тогда, когда в хандлер необходимо передать свои аргументы, помимо
event:
<ListItem
key={item.id}
onClick={e => this.сlickHandle(item.id, e)}
>
{item.name}
</ListItem>
так как движок вынужден определять контекст для стрелочной функции каждый рендер, а на это уходит дополнительное процессорное время.
Как метод теряет контекст.
Разберем на примере объекта. То же самое происходит в случае с классом, но мы будем использовать в примере объект:
var john = {
firstName: 'John',
getName() {
return this.firstName; // this - контекст вызова и это не всегда наш объект
}
}
Сценарий 1:
console.log(john.getName()); // john
Тут мы вызываем метод на объекте. Контекстом будет наш объект.
Сценарий 2:
var foo = {
firstName: 'foo',
};
var foo.getName = john.getName;
console.log(foo.getName()); // foo
Тут мы передаем метод объекта
john в свойство объекта
foo без вызова и следующей строкой вызываем его на нем. Контекстом в этот раз будет объект
foo. Ошибки не будет только потому, что у объекта
foo есть свойство
fullName
Сценарий 3:
var bar = john.getName;
console.log(bar()); // undefined
В данном случае в стандартном режиме контекстом будет
window, а в строгом режиме вылетит исключение:
Cannot read property 'firstName' of undefined
так как
this в строгом режиме будет ссылаться на
undefined
Когда вы передаете метод в колбек
onClick или в любой другой колбек события, вызов идет подобно третьему сценарию. Поэтому вы должны позаботиться о том, чтобы ваш метод не терял контекст, используя один из способов приведенных выше.