Javascript normalizer-如何生成与父实体相关的slug/id
如何使用分配与实体父级相关的id/slug 例如: 用户调用的API响应:Javascript normalizer-如何生成与父实体相关的slug/id,javascript,reactjs,redux,normalizr,Javascript,Reactjs,Redux,Normalizr,如何使用分配与实体父级相关的id/slug 例如: 用户调用的API响应: { id: '12345', firstName: 'John', images: [ { url: 'https://www.domain.com/image0', name: 'image0' }, { url: 'https://www.domain.com/image1', name: 'image1' } ] }
{
id: '12345',
firstName: 'John',
images: [
{
url: 'https://www.domain.com/image0',
name: 'image0'
},
{
url: 'https://www.domain.com/image1',
name: 'image1'
}
]
}
我可以用以下方式定义模式:
const image = new Schema('images');
const user = new Schema('users');
user.define({
images: arrayOf(image)
})
问题是图像没有id
属性,因此normalizer将无法区分它们,除非我们提供id
属性。当然,我们可以这样做
const image = new Schema('images', { idAttribute: uuid.v4() });
并生成唯一标识符
假设我们收到一个用户更新,并且一个图像的名称已经更新。因为我们在每次规范化中都会生成唯一的标识符,所以我们无法识别和更新现有图像
我需要一种方法来引用映像实体中的父实体(用户)(在其id/slug中,如12345-image0
,12345-image1
或作为单独的属性)
实现这一点的最佳方法是什么?idAttribute可以是一个函数,它接收实体、父项和引用状态片的键:
const image = new Schema('images', {
idAttribute: (entity, parent) => `${parent.id}-${entity.name}`
});
问题
以您显示的方式使用uuid将不起作用
const image = new Schema('images', { idAttribute: uuid.v4() });
uuid.v4()
理想情况下,这将起作用:
const image = new Schema('images', { idAttribute: () => uuid.v4() });
不幸的是,idAttribute
将被多次调用,如前所述。这将破坏任何实体关系。在您的示例中,图像的UID与用户实体引用的UID不同
示例输出:
users: {
'12345': {
id: '12345',
firstName: 'John',
images: [
"cj20qq7zl00053j5ws9enz4w6",
"cj20q44vj00053j5wauawlr4u"
],
}
};
images: {
cj20q44v100003j5wglj6c5h8: {
url: 'https://www.example.org/image0',
name: 'image0'
},
cj20q44vg00013j5whajs12ed: {
url: 'https://www.example.org/image1',
name: 'image1'
}
};
解决方案
解决方法是在processStrategy
回调中改变输入值,给它一个uid
属性
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'});
您现在正在对值进行变异,这很糟糕,但是idAttribute
选项使用的是输入值,而不是处理后的值
或者,您可以在idAttribute
回调中对值进行变异,这样就不会将uid
字段添加到输出值中
旁注:我建议使用cuid
npm包而不是uuid
processStrategy
不必改变值,您可以返回一个带有id字段的新对象。idAttribute
参数没有引用返回的对象,它引用了原始的值。这就是为什么我必须对原始值进行变异。(除非我弄错了,但我记得我检查过几次,我也向paul armstrong确认过)您可能是对的,getId
函数引用原始的输入,而不是过程属性,这里:和相关测试: