许多API现在返回的JSON数据都嵌套层级很深,很难直接在应用中直接使用,尤其是在使用 Redux这类库时。
在 Redux Store 中管理关系数据或嵌套数据的推荐做法是将这一部分视为数据库,并且将数据按范式化存储。
- 范式化的数据的特点:
- 任何类型的数据在 state 中都有自己的 “表”。
- 任何 “数据表” 应将各个项目存储在对象中,其中每个项目的 ID 作为 key,项目本身作为 value。
- 任何对单个项目的引用都应该根据存储项目的 ID 来完成。
- ID 数组应该用于排序。
-
🌰:
以下面的原数据为例子: image.png
数据特点是categorys为数组类型,包括所有菜单, 每个菜单category 包括此菜单下的所有菜dish, 每道菜包括此菜的所有价格price。数据嵌套级别过深,范式化处理。
处理后数据结构为:
reducer = {
categoriesIds: [cateId],
categories: {
cateId: {
...cateObj,
dishes:[dishId],
},
},
dishes: {
dishId: {
...dishesObj,
prices: [priceId]
}
},
prices: {
priceId: priceObj
},
}
- 手动实现(同事大神把FP用的出神入化)
import * as R from 'ramda';
const pair = R.compose(
R.fromPairs,
R.map(item => ([
item.id,
item,
]))
);
const format = ({ key, list, handle = R.identity }) => R.compose(
pair,
R.map(item => ({
...R.omit([key], item),
[key]: R.pluck('id', handle(item[key])),
}))
)(list);
const paradig = (data) => {
const { categorys } = data;
const categories = format({ key: 'dishes', list: categorys });
const myDishes = R.flatten(R.pluck('dishes', categorys));
const dishes = format({
key: 'prices',
list: myDishes,
handle: R.sort((a, b) => a.price - b.price),
});
const prices = pair(R.flatten(R.pluck('prices', myDishes)));
const categoryIds = R.pluck('id', categorys);
return { categoryIds, categories, dishes, prices };
};
4. Normalizr 通过定义schema,将JSON数据处理成带有ID的嵌套entities,这些entities 存储在dictionaries中。
Normalizr 处理不同的JSON数据类型,使用 不同的schema的方法,包括 Array、Entity、Object、Union以及values。 Entity 类似于标注中的实体概念,为一个处理对象。
使用 Normalizr 处理过程为:
const price = new schema.Entity('prices');
const dish = new schema.Entity('dishes',{
prices: [price]
});
const category = new schema.Entity('category',{
dishes: [dish]
})
const myCategorys = {
categorys: [category]
}
const normalizedData = normalize(data.data, myCategorys);
Normalizr真是简直了。。
网友评论