Желаемый this
не считается Child
контекстом. Функция передается как обратный вызов, она снабжена некоторым динамическим this
. Если this
является Child
экземпляром компонента, это просто совпадение.
Проблема специфична для устаревших или плохо спроектированных библиотек, которые не охватывают современный JS OOP и полагаются на произвольную динамику this
вместо передачи всех необходимых данных в качестве аргументов функции. Хорошо известный пример - библиотека D3.
Функция не может иметь два this
. Популярный обходной путь - self = this
трюк в сочетании с обычной (не стрелочной) функцией. Однако, это становится неуклюжим с синтаксисом класса, потому что это не может быть помещено снаружи constructor
:
class Parent extends React.Component {
constructor(props) {
super(props)
const self = this;
this.handleChildOnClick = function handleChildOnClick() {
// `self` is Parent instance
// `this` is dynamic context
};
}
render() {
return(
<Child
onClick={this.handleChildOnClick}
/>)
}
}
Эта перестановка неудобна, поскольку обычно ожидается, что this
будет экземпляром класса в JS OOP.
Как объяснено в этом связанном ответе , способ решения этой проблемы заключается в предоставлении вспомогательной функции, которая выполняет этот трюк внутри и отображает динамический контекст в параметре функции:
function contextWrapper(fn) {
const self = this;
return function (...args) {
return fn.call(self, this, ...args);
}
}
class Parent extends React.Component {
constructor(props) {
super(props)
this.handleChildOnClick = contextWrapper(this.handleChildOnClick.bind(this));
}
handleChildOnClick(context) {
// `this` is Parent instance
// `context` parameter is dynamic context
}
}
render() {
return(
<Child
onClick={this.handleChildOnClick}
/>)
}
}