Hamed Minaee
Hamed Minaee

Reputation: 2560

Object spread doesn't copy the object properly

I am having a strange issue using object spread. Here is my code:

const AuthenticationReducer = (state = {
authenticationObj: {
    "isAuthenticating": true, "isAuthentic": false, "subscriberId": "NA", "username": "NA",
    "firstName": "NA", "lastName": "NA", "enabled": "1", "email": "NA", isAuthorized: false
}, lastPasswordCheckStatus: undefined, isSuccessfulChangePassword:undefined,loginUserCheckStatus: undefined, createUserCheckstatus: undefined,
confirmUserCheckstatus: undefined, isSuccessfulChangeEmail:undefined, userContactInfo: {
    country: undefined,
    address1:undefined,
    address2:undefined,
    city:undefined,
    postalCode:undefined,
    phoneNumber: undefined
}
 }, action) => {

switch (action.type) {
    case SET_USER_CONTACT_INFO:
        console.log(JSON.stringify(state));
        state = {
            ...state,
            authenticationObj: {
                ...state.authenticationObj, userContactInfo: action.payload.userContactInfo
            }
        };
        console.log(JSON.stringify(state));
        console.log(action.payload.userContactInfo);

}
return state;
 };
    export default AuthenticationReducer;

Before SET_USER_CONTACT_INFO call the state is as follows:

{
"authenticationObj": {
    "isAuthenticating": false,
    "isAuthentic": true,
    "subscriberId": 4424,
    "username": "cccc",
    "firstName": "null",
    "lastName": "null",
    "email": "cccc",
    "isAuthorized": true
},
"userContactInfo": {}
}

As you see "userContactInfo": {} is empty object which make sense now as soon as SET_USER_CONTACT_INFO request is dispatched I get:

{
"authenticationObj": {
    "isAuthenticating": false,
    "isAuthentic": true,
    "subscriberId": 4424,
    "username": "vvvv",
    "firstName": "null",
    "lastName": "null",
    "email": "vvv",
    "isAuthorized": true,
    "userContactInfo": {
        "country": "Canada",
        "address1": "ssss",
        "address2": "sss",
        "city": "ssss",
        "postalCode": "ss",
        "phoneNumber": "sss"
    }
  },
    "userContactInfo": {}
 }

I get both userContactInfo one empty and one with info. It is really strange I expect the userContactInfo with new info is replaced with the empty one. what is wrong with my code? any help?

Upvotes: 0

Views: 47

Answers (2)

TPHughes
TPHughes

Reputation: 1627

This: state = { ...state, authenticationObj: { ...state.authenticationObj, userContactInfo: action.payload.userContactInfo } };

Should be: state = { ...state, userContactInfo: { ...state.userContactInfo action.payload.userContactInfo } };

You have told the script to insert the action.payload.userContactInfo into the authenticationObj, whereas it should placed as a sibling to it.

Sorry it's short I've wrote this on my phone.

Upvotes: 1

Felix Kling
Felix Kling

Reputation: 816760

I expect the userContactInfo with new info is replaced with the empty one.

The two userContactInfo are on different levels. One is at the top level, next to authenticationObj, the other is in the value of authenticationObj itself, which you easily see by looking at the indentation. Besides, an object cannot have two properties with the same name.

{
  "authenticationObj": {
    "isAuthenticating": false,
    "isAuthentic": true,
    "subscriberId": 4424,
    "username": "vvvv",
    "firstName": "null",
    "lastName": "null",
    "email": "vvv",
    "isAuthorized": true,
    "userContactInfo": {         // <root>.authenticationObj.userContactInfo
      "country": "Canada",
      "address1": "ssss",
      "address2": "sss",
      "city": "ssss",
      "postalCode": "ss",
      "phoneNumber": "sss"
    }
  },
  "userContactInfo": {}          // <root>.userContactInfo
}

I.e. you are merging the object on the wrong level. Seems what you want is

state = {
  ...state,
  userContactInfo: action.payload.userContactInfo
};

Upvotes: 3

Related Questions