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

问题描述 投票:0回答:1

我有一个名为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);
    });
  }
reactjs mobx mobx-react
1个回答
0
投票

您遇到的问题与帖子中提到的任何库无关。您应该研究thisfunction如何在JavaScript中相互交互。

这是一个很好的起点:https://github.com/getify/You-Dont-Know-JS/tree/master/scope%20%26%20closures。在经历了这个过程之后,你需要10秒才能发现错误,而不了解MobX或axios是如何工作的(问题与这些库无关)。这可能听起来很直率,但是现在花2个小时来理解这个必不可少的JS概念,将来会在4个小时内为你节省很多次。

© www.soinside.com 2019 - 2024. All rights reserved.