首页 文章

React / Redux:如何保持登录失败

提问于
浏览
2

我是React / Redux的初学者,我试图在已有的代码中做一些事情,只是为了理解它是如何工作的 . 我想编辑的部分是连接部分 . 就像现在一样,如果登录名和密码都没问题,你会转到一个新页面,如果没有,它什么都不做 .

我试图做的唯一简单的事情是通过在字段上添加红色边框向用户显示他们的登录信息是错误的 .

所以这里是我添加的代码,我将尽量不向您展示无用的代码而不是忘记有用的代码,但如果您需要更多,请告诉我 .

我做的第一件事是在 actionTypes.js 中为错误添加一个常量:

export const AUTH_REQUEST = 'AUTH_REQUEST';
export const AUTH_RECEIVE = 'AUTH_RECEIVE';
export const AUTH_ERROR = 'AUTH_ERROR';

然后在 actions/auth.js 中,我添加了authError函数,并在服务器发出失败响应后调用它:

function authRequest() {
  return {
    type: actionTypes.AUTH_REQUEST
  };
}

function authReceive(authToken) {
  return {
    type: actionTypes.AUTH_RECEIVE,
    authToken
  };
}

function authError() {
  return {
    type: actionTypes.AUTH_ERROR
  };
}

export function fetchLogin(email, password) {
  return function (dispatch) {
    dispatch(authRequest());

    const urlApi = `//${AUTH_BACKEND_HOST}:${AUTH_BACKEND_PORT}/${AUTH_BACKEND_URL.login}`
    fetch(urlApi, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'content-type': 'application/json'
      },
      body: JSON.stringify({
        email,
        password
      })
    })
    .then((response) => {
      if(response.ok) {
        // SUCCESS
        response.json().then(function(json) {
          dispatch(authReceive(json.key));
          dispatch(push('/'));
        });
      } else {
        // FAIL
        response.json().then(function(json) {
          dispatch(authError());
        });
      }
    })
    .catch(function(ex) {
      console.log(ex);
    });
  };
}

现在,在 reducers/auth.js

const initialState = {
  authToken: '',
  isFetching: false,
  error: false,
  errorMessage: ''
}

export default function (state=initialState, action) {
  switch (action.type) {
    case actionType.AUTH_REQUEST:
      return {
        ...state,
        isFetching: true
      };
    case actionType.AUTH_RECEIVE:
      return authLogin(state, action);
    case actionType.AUTH_ERROR:
      return {
        ...state,
        error: true,
        errorMessage: 'Incorrect login or password!'
      };
  }
  return state;
}

function authLogin(state, action) {
  const { authToken } = action;
  return {
    ...state,
    isFetching: false,
    authToken
  };
}

到目前为止,它似乎在我在Firefox中检查它时起作用 . 状态包含error和errorMessage值 .

所以这是我的 components/Login/presenter.jsx ,我认为它会根据状态显示正确的HTML:

import React from 'react';

const Login = React.createClass({

  handleSubmit(event) {
    event.preventDefault()

    const email = this.refs.email.value
    const password = this.refs.password.value

    this.props.onAuth(email, password);
  },

  render() {
    const { errorMessage } = this.props

      return (
        <form onSubmit={this.handleSubmit}>
          <label>Email <input ref="email" placeholder="email" required /></label>
          <label>Password <input ref="password" placeholder="password" type="password" required /></label>
<p>{errorMessage}</p> <button type="submit">Login</button> </form> ) } }); export default Login;

这里是 components/Login/index.js 我认为导入演示者并做......事情......:

import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import Login from './presenter';

function mapDispatchToProps(dispatch) {
  return {
    onAuth: bindActionCreators(actions.fetchLogin, dispatch)
  };
}

export default connect(null, mapDispatchToProps) (Login);

编辑:似乎其中一个问题是我没有将状态映射到道具 . 我尝试了Mael Razavet和azium的答案,在Login / index.js中添加了mapStateToProps:

import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import Login from './presenter';

function mapDispatchToProps(dispatch) {
  return {
    onAuth: bindActionCreators(actions.fetchLogin, dispatch)
  };
}

function mapStateToProps (state) {
  return {
    errorMessage: state.errorMessage
  };
}

export default connect(mapStateToProps, mapDispatchToProps) (Login);

但似乎errorMessage仍未定义 .

谢谢 .

1 回答

  • 2

    我想你忘了将你的状态映射到道具 . 在您的情况下,您应该将此内容添加到 components/Login/index.js

    import * as actions from './actions/auth.js';
    import Login from './presenter';
    
    const mapStateToProps = (state) => {
      return {
        error: state.login.error,
        errorMessage: state.login.errorMessage,
      };
    };
    const mapDispatchToProps = (dispatch) => {
      return {
        onAuth: (email, password) => {
          dispatch(actions.fetchLogin(email, password));      
        }
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProps)(Login); // maps your state to your component's props
    

    在你的_2553392中:

    const initialState = {
      authToken: '',
      isFetching: false,
      error: false,
      errorMessage: ''
    }
    
    export default function loginReducer(state=initialState, action) {
      switch (action.type) {
        case actionType.AUTH_REQUEST:
          return {
            ...state,
            isFetching: true
        };
        case actionType.AUTH_RECEIVE:
          return authLogin(state, action);
        case actionType.AUTH_ERROR:
          return {
            ...state,
            error: true,
            errorMessage: 'Incorrect login or password!'
          };
      }
      return state;
    }
    
    function authLogin(state, action) {
      const { authToken } = action;
      return {
        ...state,
        isFetching: false,
        authToken
      };
    }
    

    然后,在您的代码中,您应该将您的reducer组合为:

    import { combineReducers, createStore, applyMiddleware } from 'redux';
    import { Provider } from 'react-redux';
    import Login from './components/Login';
    import login from './reducers/auth.js'; //import your default reducer function
    
    //COMBINE REDUCERS
    const reducers = combineReducers({
      //reducers go here 
      login, //name of your reducer => this is is why your access your state like state.login
    });
    
    //WRAP WITH STORE AND RENDER
    const createStoreWithMiddleware = applyMiddleware()(createStore);
    
    ReactDOM.render(
      <Provider store={createStoreWithMiddleware(reducers)}>
        <Login/>
      </Provider>
      , document.querySelector('.container'));
    

    在Redux中,您可以在与实际组件不同的层(reducer)中管理状态(setState) . 为此,您需要将状态从reducer映射到组件,以便将其用作道具 . 这就是为什么在您的Login类中,您可以:

    const { errorMessage } = this.props; // now you can use errorMessage directly or this.props.errorMessage
    

    此errorMessage来自您在reducer中管理的状态,可以在组件中用作 this.props.errorMessage .

    这是教程的链接,它帮助我理解React中的Redux:https://github.com/happypoulp/redux-tutorial它应该可以帮助您更好地理解工作流程

相关问题