Angular 如何从规范化状态删除/删除项目?
我的州结构如下:Angular 如何从规范化状态删除/删除项目?,angular,typescript,redux,ngxs,Angular,Typescript,Redux,Ngxs,我的州结构如下: { entities: 1: {name: "Basketball", id: "1", leagues: Array(3)} 2: {name: "Volleyball", id: "2", leagues: Array(3)} 3: {name: "Soccer", id: "3", leagues: Array(0)} } 现在我只想删除一个id为“3”的项目 以下操作不起作用: const state = ctx.getState(); delete stat
{ entities:
1: {name: "Basketball", id: "1", leagues: Array(3)}
2: {name: "Volleyball", id: "2", leagues: Array(3)}
3: {name: "Soccer", id: "3", leagues: Array(0)}
}
现在我只想删除一个id为“3”的项目
以下操作不起作用:
const state = ctx.getState();
delete state.entities[action.id];
ctx.setState(
patch<SportTypeStateModel>({
entities: {...state.entities},
IDs: state.IDs.filter(id => id !== action.id)
})
);
正确的做法是什么 您可以过滤使用而不是删除
newEntities = state.entities.filter(item => item.id !== action.id);
ctx.setState(
patch<SportTypeStateModel>({
entities: {...newEntities },
IDs: state.IDs.filter(id => id !== action.id)
})
);
newEntities=state.entities.filter(item=>item.id!==action.id);
ctx.setState(
补丁({
实体:{…新实体},
id:state.IDs.filter(id=>id!==action.id)
})
);
最简单的方法就是过滤现有状态和补丁
const state = ctx.getState();
ctx.patchState({
entities: [...state.entities.filter(e => e.id !== action.id)],
IDs: [...state.IDs.filter(i => i !== action.id)]
}
此处未列出您正在使用的状态模型-但如果您正在存储实体,则将IDs
属性建模为@Selector
,而不是状态的一部分,因为它只是实体列表中内容的投影,例如
@Selector()
static IDs(state: YourStateModel) {
return state.entities.map(e => e.id);
}
这意味着它总是基于当前的
状态。entites
值,您不需要维护两个列表。首先,我们需要了解发生此错误的原因
NGXS在开发模式下使用引擎盖下的deepFreeze
来冻结对象。冻结您的状态(以及深度嵌套的对象/数组)以防止不可预测的突变
您可以通过调用对象进行检查。IsFrozed
:
const state=ctx.getState();
log(Object.isfreeze(state.entities));
删除state.entities[action.id];
我理解您的观点,实体
不是数组,而是对象。
所以问题是一旦一个物体被冻结,就没有办法解冻它。我们该怎么办?我们必须解冻状态对象本身、实体
对象及其子对象:
const state=ctx.getState();
const newState={…state,entities:{…state.entities};
for(Object.keys的常量键(newState.entities)){
newState.entities[key]={…newState.entities[key]};
}
log(Object.isfreeze(newState.entities));
删除newState.entities[action.id];
我不喜欢这个代码,所以不要向我扔石头:)我想你可以搜索一些包,比如deep unfreeze
,这样更具声明性。哦,我忘了IDs
属性。最后的代码是:
ctx.setState(状态=>{
常数newState={
实体:{…state.entities},
id:state.IDs.filter(id=>id!==action.id)
};
for(Object.keys的常量键(newState.entities)){
newState.entities[key]={…newState.entities[key]};
}
删除newState.entities[action.id];
返回新闻状态;
});
p.S.在本地检查了它。它不是数组。这是一个object@Poldo我认为应该是
state.entities.filter((item)=>item.id!==action.id)
并同样更正IDs:state.IDs.filter(id=>id!==action.id)
。您的结构似乎缺少括号。什么是“实体”?我想这正是我需要做的。我很惊讶没有更多关于如何使用规范化实体对象执行此操作的信息。痛苦是因为当单个实体对象包含数组属性(如leagues:[]),而每个league对象包含teams[]属性时。我可以使用lodash cloneDeep()在那里复制所有内容,但不确定是否应该复制,特别是因为我有三个存储区,分别用于运动类型、联赛和球队,并且每个实体都有一个指向父实体的引用属性。很好的解释@O.MeeKoh我是否需要更新我的答案,并对您需要的某个部分进行更多的解释,这样这个答案才能被接受?那太好了!
@Selector()
static IDs(state: YourStateModel) {
return state.entities.map(e => e.id);
}