Coder Social home page Coder Social logo

normalizr-immutable's People

Contributors

mschipperheyn avatar rseymour avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

normalizr-immutable's Issues

Cannot read property 'entities' of undefined

projects.toString() // from "state.projects", Map instance
and many other functions throw this error (eg ownProps.project.tasks.includes(taskId) there)

I saw you redefined many functions from immutable, maybe this is the source

"A record is required" error is thrown

const InvoiceRecord = Immutable.Record({
  IsFetching        : false,
  FetchDetailsError : null,
  ClientID          : null,
  ClientName        : "",
  Created           : "",
  Date              : "",
  DelegateID        : null,
  ID                : null,
  InverseTax        : null,
  Number            : null,
  Paid              : null,
  Serial            : "",
  Total             : null,
  TotalVat          : null,
  VatAtCashing      : null,
});

export class Invoice extends InvoiceRecord {
  hasFetchingError () {
    return this.FetchDetailsError !== null;
  }

  isFetching () {
    return this.IsFetching === true;
  }

  shouldFetchDetails () {
    return this.Cashing === null;
  }
}

based on official Record Class documentation

Support deep merge of different normalizr entities

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.

Proper way to merge entities

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;
}

Compatibility with transit-immutable-js

In my project I persist the state using redux-persist-transform-immutable (which uses transit-immutable-js) making it possible to store & restore Records to and from local storage. This works well for most of my state except the entities.
The problem is that when using normalizr-immutable the entities are Records containing a list of Records, which is stored/restored by redux-persist as a Map because the persistor doesn't know the structure of the entities Records.
This is how the entities reducer is persisted:
image
You can see the structure a bit: iR identifies a Record, iM identified a Map:
entities is a Record (I defined it like that in the persistor), but users is a Map containing UserRecords.

Before persisting it looks like this:
image

So after a restore, I can't access my objects anymore using number IDs so I have to convert my IDs to Strings.

I hope I'm making a bit of sense?

Do you see a way around this or should I just resort to referencing entities using a Map?

Late binding: ignoring the proxies in certain cases

You can use the proxy to get an object reference from a provided state so, you don't have to manually retrieve the id from the state. This is great because it allows you to use you normalized object structures as if they had never been normalized.

However, in some cases you want to be able to turn this off. For instance, when you merge data or when you serialize data for storage.

It would be ideal if you could late bind the state to the proxy so it will only process the proxies if the state is bound and otherwise, it will just return the id. The challenging thing is that this is a deeply nested structure.

Any ideas?

[SEO] 'normalizr-immutable' package leads to Googlebot rendering blank page on webmasters page

We used create-react-app to create react project
when I tried to include library:

import {normalize, arrayOf} from 'normalizr-immutable',

the web page failed to be rendered by Googlebot:
failed screenshot

it works after code line removed
wx20171024-150846

related packages:

"babel-polyfill": "^6.26.0",
"normalizr-immutable": "0.0.3",
"react": "^15.6.2",
"react-dom": "^15.6.2",
"immutable": "^3.8.2",
"react-redux": "^5.0.6",
"redux": "^3.6.0",
"redux-thunk": "^2.1.0",

Unnecessary overhead from harmony-reflect

Currently, we use harmony-reflect as a shim for harmony-proxies. However, you don't want this included in situations where the target environment already has full support for proxies. This should be more flexible.

reducer key per schema?

Any thoughts on allowing reducerKey to be defined on a per schema basis to support proxying across reducers?

How to handle merge entity records into NormalizedRecord?

NormalizedRecord cannot be merged with previous entities, records are replaced and not merged together as one would expect. Using mergeDeep (which would handle list concatenation) throws an error as entities is a Record and not a List.

import { Schema, arrayOf, normalize, NormalizedRecord } from 'normalizr-immutable';
import { Record } from 'immutable';

const record = Record({ id: null, name: null });
const schema = new Schema('articles', { record });

const results = normalize([
    { id: 1, name: 'One' },
    { id: 2, name: 'Two' },
    { id: 3, name: 'Three' }
], arrayOf(schema));

const more = normalize([
    { id: 4, name: 'Foo' },
    { id: 5, name: 'Bar' },
    { id: 6, name: 'Baz' }
], arrayOf(schema));

let state = NormalizedRecord();
console.log(state.entities === null);

state = state.merge(results);
console.log(state.entities.articles.size); // 3

// Uncaught Error: Cannot set unknown key "4" on Record
// state = state.mergeDeep(more); 

state = state.merge(more);
console.log(state.entities.articles.size); // 3 <-- Expected a size of 6 

Unable to import from 'normalizr-immutable'

After a normal npm install I was unable to import anything from the library.
I am unfamiliar with publishing libraries like this so I'm probably wrong, but could this be due to
no index.js being present for this library? I see no index.js in the src folder.

0.0.4 release wish

Hi, thanks for the great library. Currently the latest release on npm is still 0.0.3 which requires native Proxy support on browsers. I've tried the 0.0.4 pre-release, it already made dependency on Proxy an option.

Normally I would just be fine making my dependencies to this git repo, however this time it dosen't work if I do npm install against this git repo, as the npm run build fails silently.(on windows 10). So I had to grab the source code and build mannually.

A new release to npm would be much appreciated!

Map/Record is preferred when object key is referenced

When normalizing data by object key, a List is returned when a Map is better suited.

const json = {
    foo: 'foo',
    data: [
        { id: 1, name: 'Foo' },
        { id: 2, name: 'Bar' },
        { id: 3, name: 'Baz' }
    ]
};

const record = Record({
    id: null,
    name: null
});

const schema = new Schema('articles', {
    record
});

const normalized = normalize(json, {
    data: arrayOf(schema)
});

AFTER normalizr-immutable:

 {
    "entities":{ // Record
       "articles":{ // Record
             "1":{"id":1,"name":"Foo"},
             "2":{"id":2,"name":"Bar"},
             "3":{"id":3,"name":"Baz"}
       }
    },
    "result":[ // List ???
       ["foo", "foo"],
       ["data", [1, 2, 3]]
    ]
 }

AFTER normalizr:

 {
     "entities":{
         "articles":{
             "1":{"id":1,"name":"Foo"},
             "2":{"id":2,"name":"Bar"},
             "3":{"id":3,"name":"Baz"}
         }
     },
     "result":{
         "foo":"foo",
         "data":[1, 2, 3]
     }
 }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.