React Redux Axios:POST 请求未收到来自 redux 状态的凭据

Posted

技术标签:

【中文标题】React Redux Axios:POST 请求未收到来自 redux 状态的凭据【英文标题】:React Redux Axios: POST Request not receiving credentials from redux state 【发布时间】: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":["此字段为必填项。"]

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

【问题讨论】:

【参考方案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 协同工作的方式。感谢您的回答,我将检查您的答案是否正确,希望这将有助于其他人。干杯。

以上是关于React Redux Axios:POST 请求未收到来自 redux 状态的凭据的主要内容,如果未能解决你的问题,请参考以下文章

axios.post 调用后 Redux 更新状态太慢

取消路由更改请求 (React/Redux/Axios)

axios 不会将 post 数据发送到后端

REACT 如何使用 Redux 和 Axios(使用 promise 中间件)发出 AJAX 请求?

使用 axios 获取 400 错误错误请求

每个 axios 请求在 react-redux 应用程序中触发两次?