最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Normalizr - How to generate slugid related to parent entity - Stack Overflow

programmeradmin2浏览0评论

How can I assign id/slug related to the entity's parent using normalizr?

Example:

API Response for a user call:

{
  id: '12345',
  firstName: 'John',
  images: [
    {
      url: '',
      name: 'image0'
    },
    {
      url: '',
      name: 'image1'
    }
  ]
}

I could define my schemas in the following way:

const image = new Schema('images');
const user = new Schema('users');

user.define({
  images: arrayOf(image)
})

The problem is that images don't have an id property, so normalizr will not be able to distinguish them unless we provide an id property. Of course, we could do something like

const image = new Schema('images', { idAttribute: uuid.v4() });

and generate unique identifiers.

Suppose we receive a user update and an image's name has been updated. Because we generate unique identifiers in every normalization, we are not able to identify and update the existing image.

I need a way to reference the parent entity (user) in the image entity (either in its id/slug like 12345-image0, 12345-image1 or as a separate property.

What would be the optimal way to achieve this?

How can I assign id/slug related to the entity's parent using normalizr?

Example:

API Response for a user call:

{
  id: '12345',
  firstName: 'John',
  images: [
    {
      url: 'https://www.domain./image0',
      name: 'image0'
    },
    {
      url: 'https://www.domain./image1',
      name: 'image1'
    }
  ]
}

I could define my schemas in the following way:

const image = new Schema('images');
const user = new Schema('users');

user.define({
  images: arrayOf(image)
})

The problem is that images don't have an id property, so normalizr will not be able to distinguish them unless we provide an id property. Of course, we could do something like

const image = new Schema('images', { idAttribute: uuid.v4() });

and generate unique identifiers.

Suppose we receive a user update and an image's name has been updated. Because we generate unique identifiers in every normalization, we are not able to identify and update the existing image.

I need a way to reference the parent entity (user) in the image entity (either in its id/slug like 12345-image0, 12345-image1 or as a separate property.

What would be the optimal way to achieve this?

Share Improve this question asked Sep 24, 2016 at 21:50 Aris GoudourasAris Goudouras 3252 silver badges7 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

idAttribute can be a function that receives the entity, the parent and the key that references the slice of state:

const image = new Schema('images', {
  idAttribute: (entity, parent) => `${parent.id}-${entity.name}`
});

Problem

Using uuid the way you show will not work.

const image = new Schema('images', { idAttribute: uuid.v4() });

uuid.v4() returns a string, an acceptable value for idAttribute but now all your images will have the same uid. Not what you want.

Ideally this would work:

const image = new Schema('images', { idAttribute: () => uuid.v4() });

Unfortunately, idAttribute will be invoked multiple times, as mentioned in this issue. This will break any entity relations. In your example, the images will have different uids than what the user entity references them as.

example output:

users: {
  '12345': {
    id: '12345',
    firstName: 'John',
    images: [
      "cj20qq7zl00053j5ws9enz4w6",
      "cj20q44vj00053j5wauawlr4u"
    ],
  }
};
images: {
  cj20q44v100003j5wglj6c5h8: {
    url: 'https://www.example/image0',
    name: 'image0'
  },
  cj20q44vg00013j5whajs12ed: {
    url: 'https://www.example/image1',
    name: 'image1'
  }
};

Solution

A work around for this is to mutate the input value in the processStrategy callback, giving it an uid attribute.

const getUid = value => {
  if (!Object.prototype.hasOwnProperty.call(value, 'uid')) value.uid = uuid.v4();
  return {...value};
};

const image = new Schema('images', { processStrategy: getUid, idAttribute: 'uid'});

You're mutating the value now, so that sucks, but the idAttribute option uses the input value, not the processed value.

Alternatively, you could mutate the value in the idAttribute callback, then you would not add the uid field to the output value.

sidenote: I would remend using the cuid npm package instead of uuid

发布评论

评论列表(0)

  1. 暂无评论