Search code examples
reactjsreduxreact-reduxnormalizr

Normalizr - How to handle nested entities that are already normalized


I have entities in very nested JSON that already follow the normalizr format where the idAttribute is already the key where the object is defined:

groups: [{
  id: 'foo',
  families: {
    smiths: {
      people: [{
        id: 'sam',
      }, {
        id: 'jake',
      }],
    },
    jones: {
      people: [{
        id: 'john',
      }, {
        id: 'sue',
      }],
    },
  },
}];

In this example, notice that the families attribute is using the id (smiths, jones) to identify the people who are an array of objects with ids.

The schemas for this might look like:

const person = new Entity('person');
const family = new Entity('family', {
  people: [person],
}, {idAttribute: ???});
const group = new Entity('family', {
  family: [family],
});

QUESTION: Is there a way to specify that a schema's idAttribute is the key where it is defined? In other words, how would I define the schema for Family as it's related to groups and people?

Another question, is there a way to denormalize a flattened state so that the families families: {[id]: obj} pattern stays the same as it is in the example json above?


Solution

  • Is there a way to specify that a schema's idAttribute is the key where it is defined?

    Yes. The idAttribute function takes 3 arguments: value, parent, and key. Please read the docs. In your case, you can use the key, along with schema.Values

    const family = new schema.Entity('families', { 
        people: [ person ] 
    }, (value, parent, key) => key);
    const families = new schema.Values(family);
    const group = new schema.Entity('groups', {
        families
    });
    

    For denormalize, you'll need a separate schema for family, since the ID can't be derived from the key.