0

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'
    }]
  }
}
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
Igor Shmukler
  • 1,742
  • 3
  • 15
  • 48

2 Answers2

1

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.

moonwave99
  • 21,957
  • 3
  • 43
  • 64
1

You can merge the existing dates with the new ones, via:

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

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

const merged = {
  ...update.reduce((newState, { id, title, dates }) => ({
    ...newState,
    [id] : {
      ...newState[id],
      title,
      dates: [...newState[id]?.dates, ...dates]
    }
  }), state)
};

console.log(merged);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132