@ngrx/entity 与@ngrx/store 一起使用时无法读取未定义的属性 'ids'?在定义适配器时已经考虑了自定义 ID
@ngrx/entity `Cannot read property 'ids' of undefined` when using together with @ngrx/store? already accounting for custom ids when defining adapter
我查看了与此相关的其他 2 篇帖子,其中一篇环绕较大状态的帖子不适用,而另一篇则注册了多个 forFeature——我已经对此进行了一些测试,即使我导入了它在我的 app.module 中的 forRoot(reducers) 之前或之后没有区别。
我确定我在配置中遗漏了一些明显的东西。
我的配置:
export const orderAdapter: EntityAdapter<IOrder> = createEntityAdapter<IOrder>({
selectId: (order: IOrder) => order._id
});
export interface AllOrdersState extends EntityState<IOrder> {}
export const initialState: AllOrdersState = orderAdapter.getInitialState({
ids: [],
entities: {}
});
export const OrdersState = createFeatureSelector<AllOrdersState>('orders');
export const {
selectIds,
selectEntities,
selectAll,
selectTotal
} = orderAdapter.getSelectors(OrdersState);
我的实际减速器:
export function ordersReducer(
state: AllOrdersState = initialState,
action: actions.OrdersActions
) {
case actions.CREATE_MANY: {
console.log(action.orders);
return orderAdapter.addMany(action.orders, state);
}
}
我在 Order.Module 中注册为:
StoreModule.forFeature('orders', ordersReducer),
我的主要reducer图:
const reducers: ActionReducerMap<AppState> = {
order: orderReducer,
admin: adminReducer,
tlabs: tlabsReducer,
reports: reportsReducer,
settings: settingsReducer,
orders: ordersReducer
};
然后在app.module中主要导入:
StoreModule.forRoot(reducers),
正在尝试读取实体:
构造函数:
private store: Store<AppState>
实际函数:
this.store
.select(ordersReducer.selectAll)
导入的来源:
import * as ordersReducer from '../../../../../store/reducers/orders.reducer';
它似乎在初始化之前尝试从 OrdersState
中读取。您的 reducer 实际上并没有 return 默认状态来初始化它;至少在您提供的代码中,您似乎没有。
使你的减速器 return 成为默认状态。
export function ordersReducer(
state: AllOrdersState = initialState,
action: actions.OrdersActions
) {
switch(action.type) {
case actions.CREATE_MANY: {
console.log(action.orders);
return orderAdapter.addMany(action.orders, state);
}
default: {
return state // Here you should return the default state
}
}
}
我在 entity.js(NGRX 实现文件)中遇到了与您类似的错误。在我的例子中,我有一个延迟加载的模块,它自己的状态最初是未定义的。由于实体选择器在获取实体相关字段(例如 ID)之前不进行任何空检查,因此会导致此错误。我的解决方案是避免使用 orderAdapter.getSelectors(OrdersState)
而是定义我自己的受保护的选择器,这非常简单:
export const selectIds = createSelector(selectOrderState, (state) => state?.ids);
export const selectEntities = createSelector(selectOrderState, (state) => state?.entities);
export const selectAll = createSelector(selectOrderState, (state) => (state?.ids as Array<string|number>)?.map(id => state?.entities[id]));
export const selectTotal = createSelector(selectOrderState, (state) => state?.ids?.length);
我不喜欢我没有使用内置选择器这一事实,但至少这不会破坏我的代码。我希望 NGRX 团队提供一种方法来避免这种情况。
我遇到这个错误是因为我在设置选择器时使用了错误的功能键:
export const selectIocState = createFeatureSelector<fromIoc.IocState>('this_key_was_wrong');
它应该与您在功能模块中加载的内容相匹配:
StoreModule.forFeature('feature_key', iocReducer),
我查看了与此相关的其他 2 篇帖子,其中一篇环绕较大状态的帖子不适用,而另一篇则注册了多个 forFeature——我已经对此进行了一些测试,即使我导入了它在我的 app.module 中的 forRoot(reducers) 之前或之后没有区别。
我确定我在配置中遗漏了一些明显的东西。
我的配置:
export const orderAdapter: EntityAdapter<IOrder> = createEntityAdapter<IOrder>({
selectId: (order: IOrder) => order._id
});
export interface AllOrdersState extends EntityState<IOrder> {}
export const initialState: AllOrdersState = orderAdapter.getInitialState({
ids: [],
entities: {}
});
export const OrdersState = createFeatureSelector<AllOrdersState>('orders');
export const {
selectIds,
selectEntities,
selectAll,
selectTotal
} = orderAdapter.getSelectors(OrdersState);
我的实际减速器:
export function ordersReducer(
state: AllOrdersState = initialState,
action: actions.OrdersActions
) {
case actions.CREATE_MANY: {
console.log(action.orders);
return orderAdapter.addMany(action.orders, state);
}
}
我在 Order.Module 中注册为:
StoreModule.forFeature('orders', ordersReducer),
我的主要reducer图:
const reducers: ActionReducerMap<AppState> = {
order: orderReducer,
admin: adminReducer,
tlabs: tlabsReducer,
reports: reportsReducer,
settings: settingsReducer,
orders: ordersReducer
};
然后在app.module中主要导入:
StoreModule.forRoot(reducers),
正在尝试读取实体:
构造函数:
private store: Store<AppState>
实际函数:
this.store
.select(ordersReducer.selectAll)
导入的来源:
import * as ordersReducer from '../../../../../store/reducers/orders.reducer';
它似乎在初始化之前尝试从 OrdersState
中读取。您的 reducer 实际上并没有 return 默认状态来初始化它;至少在您提供的代码中,您似乎没有。
使你的减速器 return 成为默认状态。
export function ordersReducer(
state: AllOrdersState = initialState,
action: actions.OrdersActions
) {
switch(action.type) {
case actions.CREATE_MANY: {
console.log(action.orders);
return orderAdapter.addMany(action.orders, state);
}
default: {
return state // Here you should return the default state
}
}
}
我在 entity.js(NGRX 实现文件)中遇到了与您类似的错误。在我的例子中,我有一个延迟加载的模块,它自己的状态最初是未定义的。由于实体选择器在获取实体相关字段(例如 ID)之前不进行任何空检查,因此会导致此错误。我的解决方案是避免使用 orderAdapter.getSelectors(OrdersState)
而是定义我自己的受保护的选择器,这非常简单:
export const selectIds = createSelector(selectOrderState, (state) => state?.ids);
export const selectEntities = createSelector(selectOrderState, (state) => state?.entities);
export const selectAll = createSelector(selectOrderState, (state) => (state?.ids as Array<string|number>)?.map(id => state?.entities[id]));
export const selectTotal = createSelector(selectOrderState, (state) => state?.ids?.length);
我不喜欢我没有使用内置选择器这一事实,但至少这不会破坏我的代码。我希望 NGRX 团队提供一种方法来避免这种情况。
我遇到这个错误是因为我在设置选择器时使用了错误的功能键:
export const selectIocState = createFeatureSelector<fromIoc.IocState>('this_key_was_wrong');
它应该与您在功能模块中加载的内容相匹配:
StoreModule.forFeature('feature_key', iocReducer),