0

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

我尝试过使用不同的 HTTP 请求库 ( axios, request) 以及 Fetch API。都产生相同的结果。

runInAction()即使我没有启用严格模式,我也尝试过使用 MobX实用程序。结果相同。

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;

登录.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);
    });
  }
4

1 回答 1

0

您遇到的问题与帖子中提到的任何库都无关。您应该研究JavaScript 中彼此之间的交互方式thisfunction

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

于 2019-04-11T23:35:53.797 回答