Search code examples
javascriptreactjsreact-reduximmutable.js

Merging redux objects


I am using redux to persist state for a React.JS app.

The state keeps objects named event, which look-like {id: 2, title: 'my title', dates: [{start: '02-05-2021', end: '02-05-2021'}] } hashed by object id.

I pull objects from my backend and merge them with the existing state, inside my reducer, as:

case LOAD_SUCCESS:
  draft.loading = false;
  draft.events = {
    ...state.events,
    ...action.events.reduce((acc, val) => {
      return { ...acc, [val.id]: val };
    }, {})
  };
  break;

That is working great, adding/replacing objects already in the state by the freshly pulled version.

This is however not exactly what I need. I would like to pick the latter action.events version of the event object, except for dates. Dates I want to be merged then deduped eg have duplicates removed.

basically, if the state had

{
  2: {
    id: 2,
    title: 'my title',
    dates: [{
      start: '02-05-2021',
      end: '02-05-2021'
    }]
  }
}

and I pulled

[{
  id: 2,
  title: 'my new title',
  dates: [{
    start: '03-06-2021',
    end: '03-06-2021'
  }]
}]

the resulting state, after merge, should be

{
  2: {
    id: 2,
    title: 'my new title',
    dates: [{
      start: '02-05-2021',
      end: '02-05-2021'
    }, {
      start: '03-06-2021',
      end: '03-06-2021'
    }]
  }
}

Solution

  • Inside your reducer:

    action.events.reduce((acc, val) => {
        const existingDates = state.events[val.id]?.dates || [];
        const dates = [...val.dates, ...existingDates];
        return { ...acc, [val.id]: {...val, dates} };
    }, {})
    

    If you need to remove duplicates, see this answer.