Search code examples
reduxnormalizr

How do I use Normalizr to handle basic nested JSON?


I have a very standard nested JSON response. Projects have many dashboards. Dashboards have many charts.

What is the right way to define and use my schemas?

Below is the code for my Schemas.js, my API response, and what Normalizr converts my API response into.

Schemas.js:

import { Schema, arrayOf, normalize } from 'normalizr';

// Create a schema for each model.
const project = new Schema('projects');
const dashboard = new Schema('dashboard');
const chart = new Schema('chart');

// Projects have many dashboards.
project.define({
  dashboards: arrayOf(dashboard)
});

// Dashboards have many charts.
dashboard.define({
  charts: arrayOf(chart)
});

export const Schemas = { project, dashboard, chart };

My API response:

{
  projects: [{
    id: 1,
    name: "Project 1",
    dashboards: [{
      id: 1,
      name: "Dashboard 1",
      charts: [{
        id: 1,
        name: "Chart 1"
      },
      {
        id: 2,
        name: "Chart 2"
      }]
    },
    {
      id: 2,
      name: "Dashboard 2",
      charts: [{
        id: 3,
        name: "Chart 3"
      },
      {
        id: 4,
        name: "Chart 4"
      }]
    }]
  },
  {
    id: 2,
    name: "Project 2",
    dashboards: [{
      id: 3,
      name: "Dashboard",
      charts: []
    }]
  }]
}

When I receive this JSON in an action I do normalize(response, Schemas.project);. This seems to move the entire response into entities.projects.undefined.

{
  entities: {
    projects: {
      undefined: {
        projects: [{
          id: 1,
          name: "Project 1",
          ...
        }, ...]
      }
    }
  },
  result: undefined
}

How should I correctly define and use my schemas for this?

References:

https://github.com/gaearon/normalizr

https://github.com/reactjs/redux/blob/master/examples/real-world/actions/index.js


Solution

  • This should give you the desired result:

    normalize(response, {
        projects: arrayOf(Schemas.project)
    });
    

    The projects key is nescessary because you have an extra key in your response, and the arrayOf() indicates that the API returns an array of results.