Reputation: 1222
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?
Upvotes: 2
Views: 190
Reputation: 7911
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.
Upvotes: 2
Reputation: 7442
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!
Upvotes: 2