useSelector function is not updating the state of after dispatch function -react hooks

Viewed 11115

I am performing an authentication module where I when I click the sign in button , I am verifying user present is MySQL db or not . I am dispatching the function in here in sign in page

Basically when I dispatch it , the null state of the rSignedIn is not changed immediately after dispatch function. I am completely using react hooks. Please help me solve this , I have been trying this for three days.

But the rSignedIn state value updates when I click the login button again, in general , the when I use the state value using the useSelector the value is updated the second the time when the handleLogin() is invoked

//Sign in Page

...
...

const status=useSelector((state)=>state);
...
...
const handleLogin=(event)=>{
      dispatch(LoginUser(loginData));
      console.log(status.auth.rSignedIn);
      if(status.auth.rSignedIn){
        console.log("LOGIN success");
        History.push('/');
      }else{
        console.log("LoginFailed") ;
      }
    }

this is the action index page where I sent a request to MySQL db , then if there is a response I am dispatching it else an error.

export const LoginUser=(loginData)=>async(dispatch)=>{
    await mysqlDB.post('/fetch/retreive',loginData)
    .then((response)=>dispatch({type:ActionTypes.LOGIN_SUCCESS,payload:response.data}))
    .catch((error)=>dispatch({type:ActionTypes.LOGIN_FAILED}))
}

This is my Reducer for this :

const initialState = {
    gSignedIn:null,
    userId:null,
    registered:null,
    data:null,
    rSignedIn:null,
}


export default (state=initialState,action)=>{
    switch (action.type){
        case ActionTypes.GSIGN_IN:
            return {...state,gSignedIn:true,userId: action.payload};
        case ActionTypes.GSIGN_OUT:
            return {...state,gSignedIn:false,userId:null};
        case ActionTypes.REGISTER_SUCCESS:
            return {...state,registered:true,data: action.payload};
        case ActionTypes.REGISTER_FAILED:
            return {...state,registered:false,data:null};
        case ActionTypes.LOGIN_SUCCESS:
            return {...state,rSignedIn:true,data: action.payload};
        case ActionTypes.LOGIN_FAILED:
            return {...state,rSignedIn:false,data:null};
        case ActionTypes.LOGOUT:
            return {...state,rSignedIn:false,data:null};
        default:
            return state;
    }
};
1 Answers

dispatch will not update your state value immediately. State value is bound by closure and will only update in your next render cycle.

You can either use history.push within your action or make use of useEffect

const handleLogin=(event)=>{
      dispatch(LoginUser(loginData, History));
    }

...

export const LoginUser=(loginData, history)=>async(dispatch)=>{
    await mysqlDB.post('/fetch/retreive',loginData)
    .then((response)=>{
           dispatch({type:ActionTypes.LOGIN_SUCCESS,payload:response.data}));
           history.push('/')
    }
    .catch((error)=>{
          dispatch({type:ActionTypes.LOGIN_FAILED}))
    }
}

With the useEffect, you need to run the it only on change and not on initial render

const initialRender = useRef(true);
useEffect(() => {
   if(!initialRender.current) {
       if(state.auth.rSignedIn) {
           history.push('/');
        } else {
           console.log(not signed in);
        }
   } else {
       initialRender.current = false;
   }
}, [state.auth.rSignedIn])
Related