简体   繁体   中英

loading state never get true??(React - Redux)

I am creating an app that get the user data from the backend when the user login and display it in the user profile, i need to set loading statement like loading... in place of the profile before all data comes from the backend then display the data instead

my action creators:

export const loginUser = (loginData) => (dispatch) => {

    axios.post('/signin', loginData)
        .then(res => {
            let FBIdToken = `Bearer ${token}`;
            localStorage.setItem('FBIdToken', FBIdToken);
            dispatch(getUserData());
        })
        .catch(err => {
            dispatch({
                type: SET_ERRORS,
                payload: err.response && err.response.data
            });
        });
}

export const getUserData = () => dispatch => {
    dispatch({ type: LOADING_USER });

    axios.get('/user')
        .then(res => {
            dispatch({
                type: SET_USER,
                payload: res.data
            })
        })
        .catch(err => console.log(err))
}

reducer:

const intialState = {
    authenticated: false,
    loading: false,
    credentials: {},
};

export default (state = intialState, action) => {
    switch (action.type) {
        case SET_USER:
            return {
                authenticated: true,
                loading: false,
                ...action.payload,
            }
            case LOADING_USER:
                return {
                    loading: true,
                    ...state
                }

        default:
            return state;
    }
};

login page:

    const handleSubmit = (e) => {  
        e.preventDefault();
        loginUser(loginData);
    }

now when i click the submit button on login page handlesubmit function run the loginUser action creator that in role run the getUserData action creator.

now in getUserData action creator this action get dispatched {type: LOADING_USER} and this state should be returned from the reducer before the userData come from the backend:

{
  loading: true,
  credentials: {},
  authenticated: false
}

and then the data comes after axios request and change loading to false and set the user credentials, but this not is not the scenario in my case, as loading never get true in my code and loading... never get displayed before the user credentials set as a user profile.. what is the wrong in my code?

As I mentioned in the comment above, you need to switch the order of loading: true and ...state .

Reason: (as you guessed it) the order matters when you are spreading an object, especially if the object being spread also contains the loading key inside it. So if you keep ...state after the loading: true , it overrides the loading: true with whatever value state has for loading . And I guess that's not something we would want. Hence, keep the ...state before loading: true to get the expected result.

you are spreading the previous state after your current updated state:

case LOADING_USER:
  return {
    loading: true,
    ...state
  }

you need to do reverse:

case LOADING_USER:
   return {
     ...state,
     loading: true,              
   }

by spreading the state after your loading, your previous state got overrides the new state, but by spreading the previous state first, you overriding only the loading part of your state!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM