在MobX操作中发出HTTP请求后无法访问此内容

时间:2019-04-11 19:14:14

标签: reactjs mobx mobx-react

我有一个名为doLogin()的MobX动作。它可以在发出HTTP请求之前访问this.,但是一旦发出HTTP请求,它就变成undefined。我一直在尝试大约4个小时的箭头功能,绑定等的不同迭代,并且开始失去理智。

我尝试使用其他HTTP请求库(axiosrequest)和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);
    });
  }

1 个答案:

答案 0 :(得分:0)

您遇到的问题与文章中提到的任何库都无关。您应该研究thisfunction在JavaScript中如何相互作用。

这是一个不错的起点:https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures。经过这一步之后,您将需要10秒钟来发现错误,而不了解MobX或axios的工作方式(问题与这些库无关)。这听起来似乎有些直率,但是现在花2个小时来理解这个基本的JS概念,将在未来4个小时内为您节省很多时间。