javascriptreactjsreduxnormalizr

Spread operator overwriting elements in new object instead of combining


I'm getting data from my API, and passing it through normalizr before dumping it into redux. When I get people data from the API the reducer should append them to the people store. Right now my reducer is overwriting all existing data in the store.

The reducer:

export default function reducer(state={
    people: {
        entities : {
          people: {
            0 : {
              name : ''
            }
          }
        },
        result : [0,]
    }
  }, action) {
  switch (action.type) {
    case "GET_PEOPLE": {
      const newpPeople = {...state.people, ...action.payload };
      console.log(state.people)
      console.log(action.payload)
      console.log(newpPeople)
      return {...state, people : newpPeople};
    }
    default :
      return state
  }
}

This first console log is the state after the reducer has been used once. it has the initial set of people that i've saved to the store:

{ 
    entities: { 
                people : { 
                          1 : { id: 1, name: "jim" },
                          2 : { id: 2, name: "billy" }
                         }
              },
    result : [ 1, 2 ]
}

The second console log will be the payload of new people to be added:

{ 
    entities: { 
                people : { 
                          7 : { id: 7, name: "sally" },
                          8 : { id: 8, name: "ana" }
                         }
              },
    result : [ 7, 8 ]
}

Then the third console log should be the two states combined? But it just repeats the last one with sally and ana, and overwrites everything else.


Solution

  • That's because spread will not combine the objects recursively.

    Take a look at this simple example where it works as you expected:

    const state = { 
            entities: { 
                        people : { 
                                  1 : { id: 1, name: "jim" },
                                  2 : { id: 2, name: "billy" }
                                 }
                      },
            result : [ 1, 2 ]
        }
        
        const payload = { 
            entities: { 
                        people : { 
                                  7 : { id: 7, name: "sally" },
                                  8 : { id: 8, name: "ana" }
                                 }
                      },
            result : [ 7, 8 ]
        }
        
        const new_state = { 
            entities: { 
                        people : { 
                                  ...state.entities.people,...payload.entities.people
                                 }
                      },
            result : [...state.result,...payload.result]
        }
        
        console.log(new_state)