我有一个名为doLogin()的MobX操作。它可以在发出HTTP请求之前访问this.
,但是一旦发出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);
我希望能够在从API获得响应后在我的操作中调用this.setToken(response.data.response.token),但我无法做到。
编辑:
我用$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);
});
}
您遇到的问题与帖子中提到的任何库无关。您应该研究this
和function
如何在JavaScript中相互交互。
这是一个很好的起点:https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures。在经历了这个过程之后,你需要10秒才能发现错误,而不了解MobX或axios是如何工作的(问题与这些库无关)。这可能听起来很直率,但是现在花2个小时来理解这个必不可少的JS概念,将来会在4个小时内为你节省很多次。