1
votes

I have a authentication.reducer.js with:

export default function(state = initialState, action ){
switch(action.type) {
    case SET_CURRENT_USER:
        return {
            ...state,
            isAuthenticated: !isEmpty(action.payload),
            user: action.payload
        }

    default: 
        return state;
}}

And my Provider Context with the useReducer Hook. And a useEffect Hook for dispatch an action "setCurrentUser" and setting the "isAuthenticated" to true if the client is logged.

import authReducer from "./reducers/authentication.reducer";
...
const [stateUser, dispatch] = useReducer(authReducer, {
    isAuthenticated: false,
    user: {}
});

useEffect(()=>{
    if (localStorage.jwt) {
        const decoded = localStorage.jwt;
      
        dispatch(setCurrentUser(decoded));
    }
},[])

I put a console.log(stateUser.isAuthenticated) in my component, and this shows "false" (initial value), and then "true" (dispatch).
I need to pass the state (stateUser.isAuthenticated) to other children components but not need pass the initial value ("false").

I have a Dashboard Component (only for user logged), and in my useEffect of this component I need to do this:

if(!context.stateUser.isAuthenticated) {
        props.history.push('/login');
        
}

And in my login:

if(context.stateUser.isAuthenticated) {
        props.history.push('/');
}

This works. If I'm logged in and go to "/" is ok, and if i go to "/login", this redirect to "/".

But the problem is the re-render in the dispatch and the useReducer. the state goes: false->true, then it causes this effect: enter to "/"->"/login (false)"->"/ (true)"

How do I prevent this effect? / -> /login -> / == enter->false->true. I need : enter -> true

1
Can't you set user in the initial state to the reducer with localStorage.jwt directly instead of in useEffect? - Tholle
what if you place the useEffect currently in the Provider Context to the component that handle the login or basically the login page. Will do this change anything? - lala

1 Answers

1
votes

My recommendation would be to set isAuthenticated to null to start and only call the history functions if the state is explicitly set to true or false like so:

if (context.stateUser.isAuthenticated === false) {
    props.history.push('/login');
}

if (context.stateUser.isAuthenticated === true) {
    props.history.push('/');
}

Make sure to use the triple equals to make the comparison a strict comparison.

Does this help?

EDIT

If you were to do it this way, you would need to call setCurrentUser even if there is no user logged in.

useEffect(()=>{
    const decoded = localStorage.jwt ? localStorage.jwt : "";
    dispatch(setCurrentUser(decoded));
},[])