Search code examples
reduxnormalizr

Normalizr schema : nested entities does not become normalized


I have an Entity "term_attributes", whith two nested entities which don't become normalized. I use normalizr: "^3.2.2".

The original data is an array of products, here is the relevant bit:

[{
        "id": 9, 
        "price": "184.90",
        "term_attributes": [ 
        {
                "id": 98,
                "attribute": {
                    "id": 1,
                    "name": "Color",
                    "slug": "color"
                },
                "term": {
                    "id": 94,
                    "name": "Bags",
                    "slug": "bags"
                }
            }, 

The normalizing code:

export const termSchema = new schema.Entity('terms');
export const attributeSchema = new schema.Entity('attributes');

export const termAttributeSchema = new schema.Entity('term_attributes', { idAttribute: 'id'},{
    attribute: attributeSchema,
    term: termSchema
});

export const termAttributeListSchema = new schema.Array(termAttributeSchema);

export const productSchema = new schema.Entity('products', {
    term_attributes: termAttributeListSchema,
});

edit: forgot to add the productListSchema (not important though):

export const productListSchema = new schema.Array(productSchema);

Term_attributes are normalized, but not its nested entities (attributes and terms). Here is the result:

{
    "entities": {
"27": {
     "id": 27, 
     "price": "184.90",
     "term_attributes": [105, 545, 547, 2, 771]
},

"term_attributes": {

            "2": {
                "id": 2,
                "attribute": {
                    "id": 1,
                    "name": "Color",
                    "slug": "color"
                },
                "term": {
                    "id": 2,
                    "name": "Fashion",
                    "slug": "fashion"
                }
            },

And if I remove the"idAttribute" from the termAttributeSchema, the normalize fails:

export const termAttributeSchema = new schema.Entity('term_attributes', {
    attribute: attributeSchema,
    term: termSchema
});

^^ What's wrong here?

Update:

Paul Armstrongs solution below works, and I just skip the termAttributeListSchema and instead use the termAttributeSchema: term_attributes: termAttributeSchema.


Solution

  • Your productSchema is incorrect. It should explicitly state that term_attributes is an array, which can be done in two ways:

    Using Array shorthand:

    export const productSchema = new schema.Entity('products', {
        term_attributes: [termAttributeListSchema]
    });
    

    Or using schema.Array:

    export const productSchema = new schema.Entity('products', {
        term_attributes: new schema.Array(termAttributeListSchema)
    });