Angular @NGRX/Entity中selectAll报'ids is undefined'错误求助
我看到你在实现自定义ID的UserAdapter时遇到了selectAll报错的问题,这是NgRx Entity使用中很常见的误区,我来帮你一步步解决它。
问题根源
你的UserState是在EntityState基础上扩展了loading和failed属性,但你直接使用了UserAdapter.getSelectors()返回的默认selectAll选择器。这个默认选择器假设整个应用的state就是纯EntityState,但你的实际state结构是包含额外属性的UserState,当你调用store.select(SelectAllUsers)时,选择器会尝试从根state里直接读取ids字段,自然找不到,就抛出了ids is undefined的错误。
修复步骤
1. 创建Feature Selector定位你的UserState
首先需要创建一个selector,用来定位到Store中你的UserState对应的feature节点(这里假设你注册reducer时用的feature key是'users',如果不是请替换成你自己的key):
// 在users.reducer.ts中添加 import { createFeatureSelector } from '@ngrx/store'; export const selectUserState = createFeatureSelector<UserState>('users');
2. 传入Feature Selector获取适配后的Adapter选择器
修改你获取selectors的代码,把上面的feature selector传给getSelectors,这样Adapter就知道从哪里提取EntityState需要的ids和entities字段:
// 替换原来的selectAll获取逻辑 const { selectAll } = UserAdapter.getSelectors(selectUserState); export const SelectAllUsers = selectAll;
3. 清理多余的InitialState配置
你手动在InitialState里添加ids: []是完全多余的,UserAdapter.getInitialState()会自动初始化空的ids数组和entities对象,改成:
const InitialState = UserAdapter.getInitialState({ loading: false, failed: undefined });
额外优化:组件中的加载判断逻辑
你的组件里用if (!users)触发加载,但初始状态下selectAll会返回空数组(不是undefined),所以可以调整判断逻辑:
this.users.subscribe((users) => { console.log(users); if (users.length === 0) { // 改为判断数组长度 this.store.dispatch(LoadUsers()); } });
为什么这样能解决问题
现在SelectAllUsers会先通过selectUserState拿到完整的UserState,再从中提取出EntityState需要的核心字段(ids和entities),这样调用selectAll时就能正确找到所需数据,不会再抛出ids is undefined的错误了。
内容的提问来源于stack exchange,提问作者bloo

