Search code examples
reactjsreduxnormalizationnormalizr

Normalizr schema for array of objects for Redux


I have a current response from my api as the following:

[
   {  
      "device_id": "1234",
      "network_status": "Offline",
      "status": "Yes",
      "frequency": 50,

   },
   {  
      "device_id": "12345",
      "network_status": "online",
      "status": "no",
      "frequency": 123,

   },
   {  
      "device_id": "12346",
      "network_status": "online",
      "status": "no",
      "frequency": 423,

   },
]

Using the latest docs: https://github.com/paularmstrong/normalizr/blob/master/docs/api.md#arraydefinition-schemaattribute

I understand that these docs have been updated so looking at other questions on stack I haven't been able to find similar examples. The 'responseData' contains the response from the api which is an array of objects. [{},{},...]

My code is

import { schema } from 'normalizr';

const deviceid = new schema.Entity('device_id');
const arrayOfDevices = new schema.Array({
  device_id : deviceid,
})

normalize(responseData, arrayOfDevices)

I want to get the following output. An entity objects that has the device_id as the key for each object.

  {
  entities: {
    device_id: { 
      '1234' : {
        .....
      },
      '12345' : {
        .....
      } ,
      '123456' : {
        .....
      }
    }
  },
  result: [
    ['1234','12345','123456'],
  ]
}

However, I seemed to just be getting the following response with an empty entity and everything else being pushed into the result

 {
  entities: {},
  result: [
   {  
      "device_id": "1234",
      "network_status": "Offline",
      "status": "Yes",
      "frequency": 50,

   },
   {  
      "device_id": "12345",
      "network_status": "online",
      "status": "no",
      "frequency": 123,

   },
   {  
      "device_id": "12346",
      "network_status": "online",
      "status": "no",
      "frequency": 423,

   },
  ]
}

What do I seem to be missing for my normalizr code?


Solution

  • Normalizr expects your entities to have an id prop. If the field that contains the id has another name you have to explicitly define it:

    import { normalize, schema } from 'normalizr';
    
    const data = [
      {
        "device_id": "1234",
        "network_status": "Offline",
        "status": "Yes",
        "frequency": 50,
    
      },
      {
        "device_id": "12345",
        "network_status": "online",
        "status": "no",
        "frequency": 123,
    
      },
      {
        "device_id": "12346",
        "network_status": "online",
        "status": "no",
        "frequency": 423,
    
      },
    ];
    
    const device = new schema.Entity('devices', {}, { idAttribute: 'device_id' });
    
    const normalizedData = normalize(data, [device]);
    
    console.log(normalized);
    

    Output:

    {
        "entities": {
            "devices": {
                "1234": {
                    "device_id": "1234",
                    "network_status": "Offline",
                    "status": "Yes",
                    "frequency": 50
                },
                "12345": {
                    "device_id": "12345",
                    "network_status": "online",
                    "status": "no",
                    "frequency": 123
                },
                "12346": {
                    "device_id": "12346",
                    "network_status": "online",
                    "status": "no",
                    "frequency": 423
                }
            }
        },
        "result": [
            "1234",
            "12345",
            "12346"
        ]
    }
    

    Edit w0z95yy8zl

    Also compare with this example from the normalizr docs.

    I suggest to not name the id field device_id as that is usually superfluous if you name the variables that hold your entities correctly. If you e.g. have an array of devices you should name it devices. Then it is obvious that the id field of the objects inside is the device id. No need to repeat that in the property name.