所以我在仍然使用 NGRX 的同时找到了一些解决方法
在我开始之前,我只想说ngrx 也有提供更少样板的ngrx/data pack。但是,当我阅读它时,我找到了对我的问题的明确答案:
https://ngrx.io/guide/data/limitations
“这个库浅克隆集合中的实体数据。它不会克隆复杂、嵌套或数组属性。您必须进行深度相等测试和在请求 NgRx Data 保存数据之前克隆自己。”
我相信这对于 ngrx/entity 也是如此。
我开始寻找替代解决方案:BreezeJs、NGXS、Akita,我发现 NGXS 对我来说很快就能理解,但需要努力将我的 ngrx 实现与项目分离。
所以我回到ngrx并尝试为3级深度嵌套数据做一个解决方法
创建 3 个独立的实体状态(我将尝试使用可以减少所有样板的 ngrx/data)
创建一个函数,该函数将为每个实体返回所有必要的实体和 ID(使用 normalizr 进行规范化)
export function normalizeTrainingArray(trainings: Training[]) {
var normalized = normalize(trainings, trainingsSchema);
var entities = {
trainings: {},
exercises: {},
sets: {}
}
entities.trainings = normalized.entities.trainings ? normalized.entities.trainings : {};
entities.exercises = normalized.entities.exercises ? normalized.entities.exercises : {};
entities.sets = normalized.entities.sets ? normalized.entities.sets : {};
var ids = {
trainingIds: [],
exerciseIds: [],
setIds: []
}
ids.trainingIds = normalized.entities.trainings ? Object.values(normalized.entities.trainings).map(x => x.id) : [];
ids.exerciseIds = normalized.entities.exercises ? Object.values(normalized.entities.exercises).map(x => x.id) : [];
ids.setIds = normalized.entities.sets ? Object.values(normalized.entities.sets).map(x => x.id) : [];
return {
entities,
ids
}
这样的事情就足够了。发送 normalizeData 动作并使用效果来调用此方法并为 fetchedData 调度 3 个不同的动作...
类似于以下内容:
trainingsNormalized$ = createEffect(() =>
this.actions$.pipe(
ofType(TrainingActions.normalizeTrainings),
tap(payload => {
var normalized = normalizeTrainingArray(payload.trainings);
this.store.dispatch(TrainingActions.trainingsFetched({ entities: normalized.entities.trainings, ids: normalized.ids.trainingIds }))
this.store.dispatch(ExerciseActions.exercisesFetched({ entities: normalized.entities.exercises, ids: normalized.ids.exerciseIds }))
this.store.dispatch(SetActions.setsFetched({ entities: normalized.entities.sets, ids: normalized.ids.setIds }))
})
)
, { dispatch: false });
在一个样本缩减器中:
// GET ALL
on(TrainingActions.trainingsFetched, (state: TrainingState, payload: { entities: Dictionary<Training>, ids: string[] }) => {
return {
...state,
entities: payload.entities,
ids: payload.ids
}
}),
结果是: