Search code examples
normalizr

Accessing parent properties from processStrategy


I have the following schema:

const dataPointSchema = new schema.Entity(
  DATA_POINT_ENTITY_TYPE,
  undefined,
  {
    processStrategy: (value, parent) => {
      console.log({parent});
      return value;
    }
  }
);
const dataPointsSchema = new schema.Array(dataPointSchema);
const dataRowSchema = new schema.Entity(
  DATA_ROW_ENTITY_TYPE,
  {_embedded: {'data-points': dataPointsSchema}}
);

const dataRowsSchema = new schema.Array(dataRowSchema);

return normalize(dataRows, dataRowsSchema);

I am expecting the parent printed out when I normalize to have all the properties of the data-row, but instead it only shows the data-points that I have told it about in the dataRowSchema. Is this a bug or is this the expected behavior?

It looks like what is happening is that _embedded is what comes in as the parent in the dataPointSchema process strategy. A working example is as follows:

import {normalize, schema} from 'normalizr';

const someDataRows = [
{
  _embedded: {'data-points': [{id: 'Uv2k4uW_-6xzh8ImYNwh-0'}]},
  id: 'Uv2k4uW_-6xzh8ImYNwh',
  blah: 'hello'
},
{
  _embedded: {'data-points': [{id: '-B0jeFmCROeL5ICJpx-b'}]},
  id: 'D01A08',
  blah: 'hello1'
}
];

function normalizeRows(dataRows) {
  const dataPointSchema = new schema.Entity(
    'data-point',
    undefined,
    {
      processStrategy: (value, parent) => {
        console.log({parent});
        return value;
      }
    }
  );
  const dataPointsSchema = new schema.Array(dataPointSchema);
  const dataRowSchema = new schema.Entity(
    'data-row',
    {_embedded: {'data-points': dataPointsSchema}}
  );

  const dataRowsSchema = new schema.Array(dataRowSchema);

  return normalize(dataRows, dataRowsSchema);
}

normalizeRows(someDataRows);

Solution

  • This is the correct behavior. The parent is the parent object, which happens to be the value of _embedded. Technically speaking, plain objects are a type of non-unique schema. This could be rewritten without shorthand so it makes more sense:

    const dataRowSchema = new schema.Entity(
        'data-row',
        {_embedded: new schema.Object({'data-points': dataPointsSchema}})
    );