0
votes

In my Login component i try to login on button click, corresponding function 'handleLogin' is then getting called. In this function i dispatch an async function with my user credentials as a payload. In my saga, i am making a request putting an error to store if the response got such field, else i set a user in there. By default the error field in store is 'false'. In my component where i dispatch an action, i want to know the state of error field in store right after the successfull/unsuccessful response. When i try to login in with wrong credentials and log the state of error into the console, i first get the 'old' (initial) value of error: false, instead of error: true. Only after second login try, the error get set to true. Is there a way to know the actual state of error in store, right after dispatching async action?

Reducer:

const initialState = {
  userData: [],
  error: false
};

const userReducer = (state = initialState, action) => {
  switch (action.type) {
  case SET_USER:
    return {
      ...state,
      userData: action.payload
    }
  case SET_ERROR:
    return {
      ...state,
      error: action.payload
    }
  default:
    return state;
  }
};

SAGAS:

function* handleUserLoad(payload) {
  try {
    const user = yield call(
      loginUser,
      payload
    );
    if(user.data.errors) {
      yield put(setError(true))
    } else {
      yield put(setError(false))
      yield put(setUser(user.data.data.loginUser));
    }
  } catch (error) {
    console.log(error);
  }
}

export default function* userSaga() {
  while (1) {
    const {payload} = yield take(GET_USER);
    yield call(handleUserLoad,payload);
  }
}

PART OF LOGIN COMPONENT:

const handleLogin = async() => {
    setShouldValidate(true);
    if (allFieldsSet) {
      try {
        loginUser(user)
        // LOGIN ERROR HERE DISPLAYS THE PREVIOUS STATE 'false'
        // INSTEAD OF ACTUAL TRUE AFTER loginUser
        // IF I LOG WITH WRONG CREDENTIALS
        console.log(loginError);
      } catch (e) {
        console.error(e);
      }
    }
  };
2

2 Answers

1
votes

loginUser(user) in your component is an async function, so you can't expect console.log(loginError); to log the value of loginError correctly in next line.

Solution:

First: You can bind your login component to error state in redux. Once the state is modified by Saga based upon successful/unsuccesful response, your login component will re-render. So, in render if you will console.log then you may see the value of loginError coming correctly. So, in render only you can put the component what you want on the basis of "loginError" to be shown.

Second: You can skip using Saga and directly await for your login API response(call API using fetch/axios from here itself) in Login Component at the current place itself. In that case you will be able to get the correct login response just after the await calls gets completed and than you can continue executing your code

0
votes

I have made slight changes to default value of error in store. Now it is 'null' instead of false. And thus i can check if it was set to false/true in useEffect and do the other logic.