mschipperheyn / normalizr-immutable

Other
123 stars 13 forks source link

Support deep merge of different normalizr entities #13

Closed dbuarque closed 8 years ago

dbuarque commented 8 years ago

We have the following deep merge scenario.

  1. Our state is a new Map
const initialstate = new Map({
  isLoading:      false,
  dteUpdate:      Date.now(),
  entities:       null,
  result:         [],
  visibleResults: [],
  totalVisible:   12,
  resultCount:    0,
  currentMessage: null
});
  1. We normalize a json results and dispatch it as an action
      const normalized = normalizeJson(json.result.items, arrayOf(messageSchema), getState);
      dispatch({
        type: types.LOAD_MESSAGES,
        payload: {
            entities: normalized.entities,
           result: normalized.result,
           resultCount: json.result.items.length
       }});
  1. Then our reducer will execute this function
export function loadMessages(state, action){
  return state
          .set('isLoading', false )
          .set('dteUpdate', Date.now())
          .set('entities', action.payload.entities)
          .set('result',action.payload.result)
          .set('visibleResults',action.payload.result)
          .set('resultCount',action.payload.resultCount)
}
  1. In some point in the future someone will fire another action to merge this data with a new result
    const normalized = normalizeJson(msg, arrayOf(messageSchema),getState);
    dispatch({
      type: types.SEND_MESSAGE,
      payload: {
        entities:normalized.entities,
        result:normalized.result,
      }
    });
//-----
export function sendMessage(state, action){
  return state
        .set('isLoading', false )
        .mergeDeepIn(['entities','messages'], action.payload.entities.messages)
        .updateIn(['result'], (v) => v.push(action.payload.result))
        .updateIn(['visibleResults'], (v) => v.push(action.payload.result))
        .updateIn(['resultCount'],  (v) => v+1)
};

The data structure get merged but some mutations are made wrong in the deep level

As a normalizr-immutable user, I would like to merge deeply and be able to use all Map functions as well.

mschipperheyn commented 8 years ago

Version 0.0.4-betax should support that. There were some issues in 0.0.3 with that.

We just added support for using Map as a base for state also. That wasn't possible before, and should have been. Sorry about that.

I recommend also using a merger function that replaces List in stead of merging them. Because a general functionality of immutable is that a merge of a List, will add but NOT remove items. And that's not behaviour you generally want in a state merge.

mschipperheyn commented 8 years ago

I just noticed that when you run npm install, a wrong version of immutable may be installed (3.7.6) in stead of the correct one (3.8.1). This may lead to exceptions when merging. I filed an issue with immutablejs about this. In the meantime, you should verify if you have the correct version in your node_modules directory

https://github.com/facebook/immutable-js/issues/900

mschipperheyn commented 8 years ago

Currently, I am manually copying immutable until this is fixed