Skip to content
This repository was archived by the owner on Jan 20, 2024. It is now read-only.
This repository was archived by the owner on Jan 20, 2024. It is now read-only.

Proper way to merge entities #16

@emroot

Description

@emroot

Hey I'm having some trouble merge entities together, I might be doing something wrong, so wanted to get some feedback here first.
My view loads an initial list with basic information, the view is paginated, when I scroll down, we fetch more items from the backend, which should merge the data to the current state. When I click on an individual item, I will show the basic information, fetch more data in the background for this specific item and merge it to the entities.
I'm having issue with the merge, when I try to mergeDeep I get collection.update error.
Here's a sample of my code below:

// schema.js
import { arrayOf, Schema,  } from 'normalizr-immutable';
import { Map, Record } from 'immutable';

const reducerKey: string = 'myReducer';

/* records */
const Item: Record = new Record({
  users: new Map(),
});

const User: Record = new Record({
  id: undefined,
  fullName: undefined,
});

/* schemas */
export const itemSchema: Schema = new Schema('items', Item, { reducerKey });
export const arrayOfItems: Array = arrayOf(itemSchema);
const userSchema: Schema = new Schema('users', User, { reducerKey });

itemSchema.define({
  users: arrayOf(userSchema),
});

// actions.js
import { arrayOf, normalize } from 'normalizr-immutable';

export function fetchItem() {
  return (dispatch: Function, getState: Function) => {
    dispatch({ type: FETCH_ITEM_REQUESTED })
    Api.getItems()
      .then(payload => {
        dispatch({ 
          type: FETCH_ITEM_SUCCEEDED, 
          payload: normalize(payload.item, itemSchema, {
            getState,
            useMapsForEntityObjects: true,
            useProxyForResults: true
          })
        });
      })
      .catch(err => dispatch({ type: FETCH_ITEM_FAILED, error: true, payload: err }));
  };
}

export function fetchItems() {
  return (dispatch: Function, getState: Function) => {
    dispatch({ type: FETCH_ITEMS_REQUESTED })
    Api.getItems()
      .then(payload => {
        dispatch({ 
          type: FETCH_ITEMS_SUCCEEDED, 
          payload: normalize(payload.items, arrayOfItems, {
            getState,
            useMapsForEntityObjects: true,
            useProxyForResults: true
          })
        });
      })
      .catch(err => dispatch({ type: FETCH_ITEMS_FAILED, error: true, payload: err }));
  };
}

// reducer.js
import { NormalizedRecord } from 'normalizr-immutable';
const initialState: NormalizedRecord = new NormalizedRecord({});

export default function reducer(state: Object = initialState, action: Object) {
  const { payload, type } = action;
  switch (type) {
    case FETCH_ITEM: // Load just one item
      return state.mergeDeepIn(['entities'], payload.get('entities'));
    case PAGINATE: // On paginate add more 
      return state.mergeDeep(payload);
    case FETCH_ITEMS_SUCCEEDED: // Initial fetch
      return state.merge(payload);
    default:
      return state;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions