@ngrx/实体与@ngrx/store一起使用时"无法读取未定义的属性'ids'"?在定义适配器时已经考虑了自定义 ID



我已经查看了其他 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);
}
}

我在订单模块中注册为:

StoreModule.forFeature('orders', ordersReducer),

我的主要减速器图:

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';

我遇到了这个错误,因为我使用错误的功能键设置了我的选择器:

export const selectIocState = createFeatureSelector<fromIoc.IocState>('this_key_was_wrong');

它应该与您在功能模块中加载的内容相匹配:

StoreModule.forFeature('feature_key', iocReducer),

我在实体.js(NGRX 实现文件(中遇到了与您类似的错误。就我而言,我有一个延迟加载的模块,其自己的状态最初是未定义的。由于实体选择器在抓取实体相关字段(例如 ids(之前不会执行任何空检查,因此会导致此错误。我的解决方案是避免使用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团队能提供一种方法来避免这种情况。

看起来它正在尝试在初始化之前从OrdersState读取。您的化简器实际上不会返回默认状态以对其进行初始化;至少你似乎没有,在你提供的代码中。

使化简器返回默认状态。

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

当我忘记将"state"添加为adapter.addOne((的第二个参数时,我遇到了同样的错误。因此,在 OPs 示例中,如果 redcuer 是按以下方式编写的:

return orderAdapter.addMany(action.orders); // !! lack of "state" as 2nd param

那么错误将是完全相同的。就我而言,这是:

Uncaught TypeError: Cannot read properties of undefined (reading 'ids')
at Object.operation [as addOne] (entity.js?9b56:59:1)
at eval (eval at <anonymous> (mapping-fields-group.reducer.ts?fd4f:1:1), <anonymous>:1:17)
at eval (mapping-fields-group.reducer.ts?fd4f:13:1)
at eval (store.js?d450:1204:1)
at combination (store.js?d450:215:1)
at mappingsDataReducers (mappings-data-state.ts?7c86:21:1)
at eval (store.js?d450:265:1)
at combination (store.js?d450:215:1)
at eval (store.js?d450:254:1)
at computeNextEntry (store-devtools.js?777a:445:1)

最新更新