我正在尝试使用对象学习规范化概念。我对此有疑问
普通对象数组:
const state = {
users: [
{ id: 1, name: "Alice", posts: [{ id: 101, title: 'Post 1', comments: [{ id: 202, text: 'comment 2' }, { id: 201, text: 'comment 1' }] }] },
{ id: 2, name: "Bob", posts: [{ id: 102, title: 'Post 2', comments: [{ id: 202, text: 'comment 2' }] }] }
],
tags: [
{ id: 301, name: 'Tech', posts: [{ id: 101, title: 'Post 1' }, { id: 102, title: 'Post 2' }] },
]}
标准化结构
const state1 = {
users: {
byIds: {
1: { id: 1, name: "Alice", posts: [101] },
2: { id: 2, name: "Bob", posts: [102] }
},
allIds: [1, 2]
},
posts: {
byIds: {
101: { id: 101, title: 'Post 1', comments: [201] },
102: { id: 102, title: 'Post 2', comments: [202] }
},
allIds: [101, 102]
},
comments: {
byIds: {
201: { id: 201, text: 'comment 1' },
202: { id: 202, text: 'comment 2' }
},
allIds: [201, 202]
},
tags: {
byIds: {
301: { id: 301, name: 'Tech', posts: [101, 102] },
302: { id: 302, name: 'Travel', posts: [102] }
},
allIds: [301, 302]
}}
现在,在标准化结构内部
state1.tags.byIds['302'] = { id : 302, name: '旅行' , posts:[102] }
内部帖子[102]的价值,
state1.posts.byIds['102'] = { id : 102 , 标题: '帖子 2', 评论: [202] }
里面的评论[202]值会是这样的
state1.posts.comments['202'] = { id : 202, title: '评论 2' }
因此标签[302]值的标准化输出将是
{ id: 302, name: 'Travel', posts: { id: 102, title: 'Post 2', comments: { id: 202, text: 'comment 2' } } }
但在非标准化结构标签中302值将是
{ id: 302, name: 'Travel', posts: [{ id: 101, title: 'Post 1' }] }
这两个输出不一样,如何正确规范化以获得相同的输出?
你可以使用 normalizr 包,它
根据模式标准化嵌套 JSON
标准化嵌套数据文档提到了这个包。有关更多信息,请参阅 api 文档。
您问题的解决方案:
import { schema, normalize, denormalize } from 'normalizr';
const state = {
users: [
{
id: 1,
name: 'Alice',
posts: [
{
id: 101,
title: 'Post 1',
comments: [
{ id: 202, text: 'comment 2' },
{ id: 201, text: 'comment 1' },
],
},
],
},
{ id: 2, name: 'Bob', posts: [{ id: 102, title: 'Post 2', comments: [{ id: 202, text: 'comment 2' }] }] },
],
tags: [
{
id: 301,
name: 'Tech',
posts: [
{ id: 101, title: 'Post 1' },
{ id: 102, title: 'Post 2' },
],
},
{
id: 302,
name: 'Travel',
posts: [{ id: 102, title: 'Post 2' }],
},
],
};
const comment = new schema.Entity(
'comments',
{},
{
processStrategy: (value, parent) => {
return { ...value, post: parent.id };
},
},
);
const post = new schema.Entity('posts', { comments: new schema.Array(comment) });
const user = new schema.Entity('users', { posts: new schema.Array(post) });
const tag = new schema.Entity('tags', { posts: new schema.Array(post) });
const responseSchema = new schema.Object({ users: new schema.Array(user), tags: new schema.Array(tag) });
const normalizedData = normalize(state, responseSchema);
console.log('normalizedData: ', JSON.stringify(normalizedData, null, 2), '\n');
const tagId = '302';
const denormalizedData = denormalize({ tags: [tagId] }, responseSchema, normalizedData.entities);
console.log('denormalizedData: ', JSON.stringify(denormalizedData, null, 2), '\n');
console.log('tag[302]: ', JSON.stringify(denormalizedData.tags[0], null, 2));
日志:
normalizedData: {
"entities": {
"comments": {
"201": {
"id": 201,
"text": "comment 1",
"post": 101
},
"202": {
"id": 202,
"text": "comment 2",
"post": 102
}
},
"posts": {
"101": {
"id": 101,
"title": "Post 1",
"comments": [
202,
201
]
},
"102": {
"id": 102,
"title": "Post 2",
"comments": [
202
]
}
},
"users": {
"1": {
"id": 1,
"name": "Alice",
"posts": [
101
]
},
"2": {
"id": 2,
"name": "Bob",
"posts": [
102
]
}
},
"tags": {
"301": {
"id": 301,
"name": "Tech",
"posts": [
101,
102
]
},
"302": {
"id": 302,
"name": "Travel",
"posts": [
102
]
}
}
},
"result": {
"users": [
1,
2
],
"tags": [
301,
302
]
}
}
denormalizedData: {
"tags": [
{
"id": 302,
"name": "Travel",
"posts": [
{
"id": 102,
"title": "Post 2",
"comments": [
{
"id": 202,
"text": "comment 2",
"post": 102
}
]
}
]
}
]
}
tag[302]: {
"id": 302,
"name": "Travel",
"posts": [
{
"id": 102,
"title": "Post 2",
"comments": [
{
"id": 202,
"text": "comment 2",
"post": 102
}
]
}
]
}