使用react redux

时间:2017-09-29 19:08:36

标签: reactjs react-native redux react-redux

我正在使用react native和redux实现登录页面。这是我的reducer的示例代码。有三种类型; types.SUBMIT_LOGIN,types.CHANGE_USERNAME,types.CHANGE_PASSWORD。

CHANGE_USERNAME和CHANGE_PASSWORD工作正常。但问题是SUBMIT_LOGIN。我猜它是因为异步状态的变化。无论如何在那里使用fetch()方法改变状态??

export default function login(state = initialState, action = {}) {
  switch (action.type) {
    case types.SUBMIT_LOGIN: {
      let loginStatus = false;

      if (state.username != null && state.password != null
        && state.username.length > 0 && state.password.length > 0
        && state.username === state.password) {
        loginStatus = true;
      } else {
      let updatedErrMsg = '';
      fetch('https://staging-barrie.mpower.ca/mpower/mpp/weblogin2.action?username='+state.username+'&password='+state.password,
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36',
        },
      }
      )
      .then((response) => response.json())
      .then((responseJson) => {
        if (responseJson.result === 'success') {
          loginStatus = true;
        } else {
          loginStatus = false;
          updatedErrMsg = 'Incorrect Username or Password.';
        }
          return {
            ...state,
            isLoggedIn: loginStatus,
            errorMsg: updatedErrMsg
          };
        });
      }
      return {
        ...state,
        isLoggedIn: loginStatus
      };

    }

  case types.CHANGE_USERNAME:
    return {
      ...state,
      username: action.username
    };

  case types.CHANGE_PASSWORD:
    return {
      ...state,
      password: action.password
    };

  default:
    return state;

} }

2 个答案:

答案 0 :(得分:2)

我相信您可以通过使用Thunk中间件来实现这一目标:

https://github.com/gaearon/redux-thunk

使用此功能,您可以创建一个异步操作创建器,最终将调度操作以更新状态。通过在将其送入减速器之前创建动作,您应该规避您在此处遇到的任何问题。

首先,您要定义一个简单的操作

const submitLogin(loginStatus, errorMessage){
  return {
    type: SUBMIT_LOGIN,
    loginStatus,
    errorMessage
  }
}

然后,您将创建异步操作,最终将调度该操作,并将获取的结果作为参数传递

const thunk = ()=>{
  return (dispatch, getState)=> {
    <async action goes here>
    dispatch(submitLogin(loginStatus, errorMessage));
  }
}

然后,您可以在reducer中构建一个更简单的操作,根据您提供的简单操作更新状态。您将要在您的代码中的任何位置导入thunk action creator

答案 1 :(得分:1)

你应该避免在reducer中使用异步调用。您应该有一个单独的方法来执行异步调用,并且当该调用完成时,它将相应地调度一个操作(在您的情况下为SUBMIT_LOGIN)。

保留单独的功能,并在请求完成时发送操作,如此

function loginUser () {
     let loginStatus = false;

     if (state.username != null && state.password != null
        && state.username.length > 0 && state.password.length > 0
        && state.username === state.password) {
        loginStatus = true;
      } else {
      let updatedErrMsg = '';
      fetch('https://staging-barrie.mpower.ca/mpower/mpp/weblogin2.action?username='+state.username+'&password='+state.password,
      {
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36',
        },
      }
      )
      .then((response) => response.json())
      .then((responseJson) => {
        if (responseJson.result === 'success') {
          loginStatus = true;
        } else {
          loginStatus = false;
          updatedErrMsg = 'Incorrect Username or Password.';
        }
        // Request is complete so dispatch an action.
        dispactch({type: types.SUBMIT_LOGIN, payload: {loginStatus,updatedErrMsg }})
      })
}

保持你的减速机清洁。它应该根据action.type

返回一个新状态
export default function login(state = initialState, action = {}) {
  switch (action.type) {
   case types.SUBMIT_LOGIN:
     return {
       ...state,
       isLoggedIn: action.payload.loginStatus,
       errorMsg: action.paylod.updatedErrMsg
     };

  case types.CHANGE_USERNAME:
    return {
      ...state,
      username: action.username
    };

  case types.CHANGE_PASSWORD:
    return {
      ...state,
      password: action.password
    };

  default:
    return state;