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);
}