У меня есть действие MobX, называемое doLogin ().Он может получить доступ к this.
перед выполнением HTTP-запроса, но как только HTTP-запрос будет выполнен, он станет undefined
.Я пробовал разные итерации функций стрелок, привязок и т. Д. Около 4 часов и начинаю сходить с ума.
Я пытался использовать разные библиотеки HTTP-запросов (axios
, request
)а также Fetch API.Все дают одинаковый результат.
Я пытался использовать утилиту MobX runInAction()
, хотя у меня не включен строгий режим.Тот же результат.
AuthStore.js
import { observable, action } from "mobx";
import axios from "axios";
class AuthStore {
@observable token = "";
@observable isLoggedIn = false;
@observable loading = false;
@observable error = null;
@action setToken = (token) => {
this.token = token;
this.isLoggedIn = true;
this.loading = false;
}
@action doLogin = (email, password) => {
this.loading = true; // works as expected
console.log("this before: ", this); // prints AuthStore
axios.post('http://my-api.com/users/authenticate', {
email: email,
password: password
})
.then(function (response) {
console.log("this after: ", this); // prints undefined
this.setToken(response.data.response.token); // err
})
.catch(function (error) {
console.log("Auth store error ", error);
});
}
}
const store = new AuthStore();
export default store;
Login.js
import React from "react";
import { Form, Input, Button, Checkbox } from 'antd';
import { inject, observer } from 'mobx-react';
import "./Login.less";
@inject('AuthStore')
@observer
export default class Login extends React.Component {
componentDidMount() {
// To disabled submit button at the beginning.
this.props.form.validateFields();
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.AuthStore.doLogin(values.email, values.password);
}
});
}
hasErrors = (fieldsError) => {
return Object.keys(fieldsError).some(field => fieldsError[field]);
}
render() {
const { loading } = this.props.AuthStore;
const { getFieldDecorator, getFieldsError, getFieldError, isFieldTouched } = this.props.form;
const emailError = isFieldTouched('email') && getFieldError('email');
const passwordError = isFieldTouched('password') && getFieldError('password');
return (
<div id="login">
<Form onSubmit={this.handleSubmit} className="login-form">
<Form.Item validateStatus={emailError ? 'error' : ''} help={emailError || ''}>
{getFieldDecorator('email', {
rules: [{ required: true, message: 'Please input your email!' }],
})(
<Input prefix={<i className="far fa-user"></i>} placeholder="Username" />
)}
</Form.Item>
<Form.Item validateStatus={passwordError ? 'error' : ''} help={passwordError || ''}>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<i className="far fa-lock"></i>} type="password" placeholder="Password" />
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: true,
})(
<Checkbox>Remember me</Checkbox>
)}
<a className="login-form-forgot" href="">Forgot password</a>
<Button type="primary" htmlType="submit" className="login-form-button" loading={loading} disabled={this.hasErrors(getFieldsError())}>
Log in
</Button>
Don't have an account? <a href="">Register now!</a>
</Form.Item>
</Form>
</div>
);
}
}
Login = Form.create({})(Login);
Я ожидаю, что смогу вызвать this.setToken (response.data.response.token) в моем действии после получения ответа от API, но я не могу.
edit:
Я исправил это с помощью $this=this
.Не уверен, что это правильный способ решения проблемы, но это всего лишь личный проект, и после того, как я уже потратил часы на эту одну функцию, я закончил.
Так что теперь это выглядит как
@action doLogin = (email, password) => {
const $this = this
this.loading = true; // works as expected
axios.post('http://my-api.com/users/authenticate', {
email: email,
password: password
})
.then(function (response) {
$this.setToken(response.data.response.token);
})
.catch(function (error) {
console.log("Auth store error ", error);
});
}