我有一个名为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);
});
}
答案 0 :(得分:0)
您遇到的问题与文章中提到的任何库都无关。您应该研究this
和function
在JavaScript中如何相互作用。
这是一个不错的起点:https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures。经过这一步之后,您将需要10秒钟来发现错误,而不了解MobX或axios的工作方式(问题与这些库无关)。这听起来似乎有些直率,但是现在花2个小时来理解这个基本的JS概念,将在未来4个小时内为您节省很多时间。