【问题标题】:React Redux Axios: POST Request not receiving credentials from redux stateReact Redux Axios:POST 请求未收到来自 redux 状态的凭据
【发布时间】:2018-04-19 04:39:52
【问题描述】:

我一直在对我的项目进行身份验证。我有一个提供 JWT 令牌的 REST api 后端。我的前端堆栈是 ReactJS、Redux、Axios 和 Redux Thunk。

我的问题是为什么当我提交表单时它没有发送任何凭据?

但是当我在 credChange 上控制台记录操作和有效负载时,它似乎是正确的。我不是在某处设置状态吗? 此外,axios 不会捕获 400 Bad Request 错误。

这是我的代码:

AuthActions.js

export const credChange = ({ prop, value }) => {
  return {
    type: CRED_CHANGE,
    payload: { prop, value },
  };
};
export const logoutUser = () => {
  return (dispatch) => {
    dispatch({ type: LOGOUT_USER });
  };
};
const loginSuccess = (dispatch, response) => {
  dispatch({
    type: LOGIN_USER_SUCCESS,
    payload: response.data.token,
  });
};
const loginError = (dispatch, error) => {
  dispatch({
    type: LOGIN_USER_ERROR,
    payload: error.response.data,
  });
};
export const loginUser = ({ empNum, password }) => {
  return (dispatch) => {
    dispatch({ type: LOGIN_USER });
    axios({
      method: 'post',
      url: 'http://127.0.0.1:8000/profiles_api/jwt/authTK/',
      data: {
        emp_number: empNum,
        password,
      },
    })
      .then(response => loginSuccess(dispatch, response))
      .catch(error => loginError(dispatch, error));
  };
};

AuthReducer.js

const INITIAL_STATE = {
  empNum: '',
  password: '',
  empNumErr: null,
  passwordErr: null,
  authTK: null,
  loading: false,
};

export default (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case CRED_CHANGE:
      return { ...state, [action.payload.prop]: action.payload.value };
    case LOGIN_USER:
      return {
        ...state,
        ...INITIAL_STATE,
        loading: true,
      };
    case LOGOUT_USER:
      return {
        ...state,
        INITIAL_STATE,
      };
    case LOGIN_USER_SUCCESS:
      return {
        ...state,
        ...INITIAL_STATE,
        authTK: action.payload,
      };
    case LOGIN_USER_ERROR:
      return {
        ...state,
        ...INITIAL_STATE,
        empNumErr: action.payload.emp_number,
        passwordErr: action.payload.password,
      };
    default:
      return state;
  }
};

LoginForm.js

import React, { Component } from 'react';
import { connect } from 'react-redux';

import {
  credChange,
  loginUser,
  logoutUser,
} from '../Actions';

class LoginForm extends Component {
  constructor() {
    super();
    this.onFormSubmit = this.onFormSubmit.bind(this);
    this.renderEmpNumErr = this.renderEmpNumErr.bind(this);
    this.empNumChange = this.empNumChange.bind(this);
    this.passwordChange = this.passwordChange.bind(this);
  }
  onFormSubmit() {
    const { empNum, password } = this.props;
    this.props.loginUser({ empNum, password });
  }
  empNumChange(text) {
    this.props.credChange({ prop: 'empNum', value: text.target.value });
  }
  passwordChange(text) {
    this.props.credChange({ prop: 'password', value: text.target.value });
  }
  renderEmpNumErr() {
    if (this.props.empNumErr) {
      return (
        <p>
          {this.props.empNumErr}
        </p>
      );
    }
    return null;
  }
  render() {
    return (
      <div>
        <form onSubmit={this.onFormSubmit}>
          <label htmlFor="numberLabel">Employee Number</label>
          <input
            id="numberLabel"
            type="password"
            value={this.props.empNum}
            onChange={this.empNumChange}
          />
          <label htmlFor="passLabel">Password</label>
          <input
            id="passLabel"
            type="password"
            value={this.props.password}
            onChange={this.passwordChange}
          />
          <button type="submit">Login</button>
        </form>
        {this.renderEmpNumErr()}
      </div>
    );
  }
}

const mapStateToProps = ({ counter }) => {
  const {
    empNum,
    password,
    loading,
    empNumErr,
    passwordErr,
    authTK,
  } = counter;
  return {
    empNum,
    password,
    loading,
    empNumErr,
    passwordErr,
    authTK,
  };
};

export default connect(mapStateToProps, { credChange, loginUser, logoutUser })(LoginForm);

提交带有凭据的表单后

控制台说:

POST XHR http://127.0.0.1:8000/profiles_api/jwt/authTK/ [HTTP/1.0 400 Bad Request 5ms]

POST 请求原始数据为空白,因此未发送任何凭据。

{"emp_number":["此字段为必填项。"],"password":["此字段为必填项。"]}

编辑 如果我可以提供任何其他信息,请说出来,但我认为这应该足够了。

【问题讨论】:

    标签: reactjs redux react-redux axios redux-thunk


    【解决方案1】:

    看起来 empNum 和 password 没有在该状态下设置。这是因为 credChange 返回的 action 对象没有被调度,所以 reducer 永远不会被调用:

    // dispatch calls the reducer which updates the state
    dispatch(actionCreator())
    
    // returns an action object, doesn't call reducer
    actionCreator() 
    

    您可以通过调用绑定动作创建者来自动调度动作:

    // calls the reducer, updates the state
    const boundActionCreator = () => {dispatch(actionCreator())}
    
    // call boundActionCreator in your component
    boundActionCreator()
    

    mapDispatchToProps 可用于定义绑定的动作创建者(作为道具传递):

    const mapDispatchToProps = (dispatch) => {
    
      return {
          credChange: ({ prop, value }) => {dispatch(credChange({prop, value})},
          loginUser: ({ empNum, password }) => {dispatch(loginUser({empNum, password})},
          logoutUser: () => {dispatch(logoutUser()},
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(LoginForm);
    

    这应该解决状态更新问题,允许从状态(empNumber、密码等)读取的道具也更新。

    【讨论】:

    • loginUser 正在被调度。 onFormSubmit() 调度它。这是经过验证的,因为 axios 请求会通过。问题是凭据为空。我只需要弄清楚为什么在调用 axios 请求时,应该在 empNum 和 password 中的值是空白的。这显然不是预期的行为。有任何想法吗? 编辑 也许我错了,我仍然遗漏了一些东西。如果是这样,你能详细说明吗? @GraysonLangford
    • 您的回答将我引向了正确的方向。我最终在组件级别状态上更新了 empNum 和密码,然后 onSubmit 发送了操作以使用凭据登录。这是有效的,但它是最好的选择吗?我问是因为我在后端构建的身份验证系统使用 JWT,并且我打算使登录超时和刷新功能。也许将凭据保持在 redux 状态是刷新登录等的方法。@GraysonLangford
    • 此线程可能会回答您的问题:github.com/reactjs/redux/issues/1287 如果其他地方不需要 empNum 和密码,最好将它们保持在本地组件状态。如果稍后您发现其他组件需要访问它们(并且作为 props 传递是不可能的或需要向下传递太多级别),总是可以返回到全局 redux 状态。
    • 你很有帮助@Grayson Langford!谢谢你。你指给我的线程回答了我的问题。我只需要花时间了解 react 和 redux 协同工作的方式。感谢您的回答,我将检查您的答案是否正确,希望这将有助于其他人。干杯。
    猜你喜欢
    • 2021-01-10
    • 1970-01-01
    • 2020-09-11
    • 2019-05-30
    • 2017-11-07
    • 2021-01-08
    • 2021-08-04
    • 2020-09-15
    • 2016-04-21
    相关资源
    最近更新 更多