tkss
tkss

Reputation: 175

Dispatch right after another dispatch overwrites state

I'm new to React and react-redux and I'm having a lot of trouble with dispatches and updating the state

After the response from the server, if the user is authenticated I proceed to do below

this.props.dispatch(addAuth(logged.user));
this.props.dispatch(updateAvatar(logged.user.avatar)) 

However, after I do that the log is

{type: "AUTHENTICATE", user: "cash"} //(LOGGING ACTION FROM REDUCER)
{isAuth: true, username: "cash", myAvatar: undefined, dispatch: ƒ}

{type: "UPDATE_AVATAR", updateAvatar: "http://www.example.com/1234.jpg"} //(LOGGING ACTION FROM REDUCER)
{isAuth: undefined, username: undefined, myAvatar: undefined, dispatch: ƒ}

Here's the initial state

const intialState = {
    isAuth: false,
    username: '',
    myAvatar: ''
};

Actions

function addAuth(user){
    return {
        type: 'AUTHENTICATE', 
        user: user.username,
    };

}

function updateAvatar(avatarLink){
    return {
        type: 'UPDATE_AVATAR', 
        updateAvatar: avatarLink
    };
}

Reducer

function reducer(state = intialState, action) {
    switch(action.type){
        case 'AUTHENTICATE':
        return {
            isAuth: true,
            username: action.user,
        };
        case 'LOGOUT':
        return {
            isAuth: false
        }
        case 'UPDATE_AVATAR':
        return {
            myAvatar: action.updateAvatar
        };
        default:
            return state;
    }
}

My desired outcome is to update the isAuth and username and then just update the avatar state like so

{isAuth: true, username: "cash", myAvatar: undefined, dispatch: ƒ}
{isAuth: true, username: "cash", myAvatar: "http://www.example.com/1234.jpg", dispatch: ƒ}

Upvotes: 0

Views: 578

Answers (1)

sn42
sn42

Reputation: 2444

Your return a new object without specifying all properties, leaving some undefined.

If you want to create a copy of the old state and alter this new object Object.assign should be what you are looking for. According to redux docs this should be the reducer for your AUTHENTICATE action:

return Object.assign({}, state, {
    isAuth: true,
    username: action.username
})

The other actions can be rewritten the same way, if you intend to copy the other unspecified values.

A note from the docs:

We don't mutate the state. We create a copy with Object.assign(). Object.assign(state, { visibilityFilter: action.filter }) is also wrong: it will mutate the first argument. You must supply an empty object as the first parameter. You can also enable the object spread operator proposal to write { ...state, ...newState } instead.

Upvotes: 1

Related Questions