使用normalizr对Redux状态产品数据反规范化失败求助
解决Redux反规范化产品数据的问题
兄弟,我太懂你这种卡反规范化的崩溃了——一会儿返回个光秃秃的ID,一会儿直接报个找不到实体的错,折腾起来真的头大!咱们一步步拆解问题,把坑填上:
问题根源拆解
先看你给出的规范化后的数据结构:
state.data: { products: { products: { 9: { id:9, attributes: [10,45,23], things: [23,55,77] }, 11: //... }, attributes: { 10: { id:10 }, 45: //... }, things: { //... } } }
你传给denormalize的entities是state.data.products,这个结构是对的——它包含了products、attributes、things三个实体集合,和normalize返回的entities结构完全匹配。那两种写法为啥都不对?
- 用
[productSchema]时:你告诉denormalize要处理数组类型的实体,但你传入的是单个ID(9),它会把这个ID当成数组的一个元素,自然直接返回9——相当于“你要反规范化一个数组,但只给了一个ID,那这个ID本身就是结果”。 - 不用数组时报错
entities[schemaKey] is undefined:核心问题大概率是你的子schema的键名和entities里的顶级键名不匹配!
核心错误点(你找到的问题应该就是这个)
你定义productSchema时嵌套了attributes: [attributeSchema]和things: [thingsSchema],但如果你的attributeSchema或thingsSchema的键名和entities里的键名不一致,就会触发这个错误。
举个反例:如果你的属性schema是这么写的:
// 错误写法:键名是单数attribute,和entities里的attributes不匹配 const attributeSchema = new schema.Entity('attribute');
那denormalize去找entities.attribute时自然找不到,直接报错。
修正后的完整解决方案
1. 确保所有Schema的键名和Entities一致
所有子schema的键名必须和entities里的顶级键名完全对应(复数/单数要一致):
// 正确的子Schema定义 const attributeSchema = new schema.Entity('attributes'); // 和entities.attributes对应 const thingsSchema = new schema.Entity('things'); // 和entities.things对应 const productSchema = new schema.Entity('products', { attributes: [attributeSchema], things: [thingsSchema] });
2. 正确编写反规范化函数
反规范化单个实体时,第二个参数用单个Schema对象(不要包数组),同时注意ID的类型匹配(比如你的实体键是字符串的话,要把数字ID转成字符串):
export const denormalizeProduct = (state, productId) => { const entities = state.data.products; // 处理ID类型匹配:如果entities里的键是字符串,转一下传入的ID const normalizedId = typeof productId === 'number' ? String(productId) : productId; // 这里用单个productSchema,不是数组! return denormalize(normalizedId, productSchema, entities); }
3. 验证调用
现在调用denormalizeProduct(state, 9),应该就能返回完整的、包含关联属性和things的产品对象了。
内容的提问来源于stack exchange,提问作者Galivan
相关产品推荐
相关产品推荐

