В моем приложении основной компонент определяет функцию, которая имеет ссылку на локальную функцию, например:
class Root extends React.Component {
constructor(props) {
super(props);
}
tokenizer({email, password}) {
return this.props.client.query({
query: getToken,
variables: {email: email, password: password}
}).then(response => {
return response.data
}).catch(error => {
console.warn(error);
return {}
});
}
async fetchToken({email, password}) {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
render() {
if (this.props.token) {
return (
<Home />
)
} else {
return <Login fetchToken = {this.fetchToken} />;
}
}
}
Дочерний компонент (а именно Login) будет использовать функцию fetchToken следующим образом:
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
this.handleChangeEvent = this.handleChangeEvent.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeEvent(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
this.props.fetchToken(this.state);
}
render() {
return (
<Form onSubmit = {this.handleSubmit}>
// ... Form HTML here
</Form>
)
}
}
Теперь, когда форма отправлена, fetchToken не может ссылаться на this.tokenizer из-за следующей ошибки: Uncaught (in promise) TypeError: this.tokenizer is not a function
Я мог бы передать метод tokenizer, но он, в свою очередь, ссылается на другие реквизиты. Таким образом, мне пришлось бы передать любую функцию/состояние/реквизит, связанную с этим, что кажется излишним. Вместо этого можно было бы вызывать fetchToken только сославшись на него в родительском элементе?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы должны связать все свои методы, если хотите использовать их в одном контексте. Самый простой способ сделать это — использовать функцию стрелки в вашем классе для каждого метода.
class Root extends React.Component {
tokenizer = async ({email, password}) => {
return this.props.client.query({
query: getToken,
variables: {email: email, password: password}
}).then(response => {
return response.data
}).catch(error => {
console.warn(error);
return {}
});
}
fetchToken = async ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
render() {
if (this.props.token) {
return (
<Home />
)
} else {
return <Login fetchToken = {this.fetchToken} />;
}
}
}
Не уверен, как я пропустил это. Я связал функцию через конструктор как таковой this.fetchToken = this.fetchToken.bind(this);
fetchToken не имеет ссылки на this, поэтому вам нужно либо привязать его, либо использовать функцию стрелки. Чтобы привязать его, вы должны привязать его к this, как вы делаете это с handleChangeEvent и handleSubmit в конструкторе вашего компонента входа в систему.
В качестве стрелочной функции ваш fetchToken будет выглядеть так:
async fetchToken = ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
Я предлагаю сделать то же самое с токенизатором.
Как показывает ошибка, при выполнении этой строки кода возникает ошибка типа:
const data = await this.tokenizer({email, password});
вы вызываете функцию tokenizer с помощью this, но на самом деле this теперь не указывает на тот же объект. если вы console.info(this.tokenizer) это даст вам undefined. Да! вы улавливаете проблему, проблема заключается в масштабе. позвольте мне немного объяснить вам область применения this:
Когда она находится внутри метода объекта, владельцем функции является объект. Таким образом, ключевое слово this привязано к объекту.
Тем не менее, когда он находится внутри функции, отдельной функции или внутри другой функции, this всегда будет относиться к глобальной области видимости.
Это известно как причуда JavaScript, означающее что-то, что просто происходит в JavaScript, что не совсем просто и работает не так, как вы думаете. Это также было расценено разработчиками как плохой выбор дизайна, который они теперь исправляют с помощью стрелочных функций ES6.
Вы можете либо привязать свой метод, который разработчики использовали до ES6, либо теперь вы можете просто использовать функцию стрелки. вот так
async fetchToken = ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
Точно так же вы можете сделать функцию токенизатора также функцией стрелки.
Можно ли привязать функции токенизатора, fetchToken?
tokenizer = ({email, password}) => {иawait fetchToken = () =>