NGRX Selector报错:Cannot read properties of undefined (reading 'x') 求助
问题背景
正在学习NGRX,参考教程视频实践,当前使用Angular独立组件模式,已在main.ts中配置provideStore,路由中通过provideState提供customer状态与Effects。Redux控制台显示数据正常切换,但HTML中使用*ngrxLet绑定Observable时,每个Observable都触发错误:ERROR TypeError: Cannot read properties of undefined (reading 'x')。
已尝试使用hasOwnProperty校验、移除所有index.ts文件,均未解决问题。
相关代码
测试组件代码
@Component({ selector: 'app-one', standalone: true, imports: [ CommonModule, LetModule ], templateUrl: './one.component.html', styleUrls: ['./one.component.scss'] }) export class OneComponent implements OnInit { private store = inject(Store<AppStateInterface>); isLoading$: Observable<boolean> = this.store.select(customerLoadingSelector); customer$: Observable<Customer | null> = this.store.select(customerSelector); error$: Observable<string | null> = this.store.select(errorSelector); ngOnInit(): void { this.store.dispatch(getCustomer()); } }
HTML代码
<p *ngrxLet="isLoading$ as loading">loading: {{loading}}</p> <p *ngrxLet="error$ as error">error: {{error}}</p> <p *ngrxLet="customer$ as customer">customer: {{customer}}</p>
Actions代码
export const getCustomer = createAction('[Customer] get Customer'); export const getCustomerSuccess = createAction('[Customer] get Customer success', props<{ customer: Customer; }>()); export const getCustomerFailure = createAction('[Customer] get Customer failure', props<{ error: string; }>());
Reducer代码
export const initialState: CustomerStateInterface = { isLoading: false, customer: null, error: null }; export const customerReducer = createReducer( initialState, on(getCustomer, (state) => ({ ...state, isLoading: true })), on(getCustomerSuccess, (state, action) => ({ ...state, isLoading: false, customer: action.customer })), on(getCustomerFailure, (state, action) => ({ ...state, isLoading: true, error: action.error })) );
Selector代码
export const selectCustomer = (state: AppStateInterface) => state.customer; export const customerLoadingSelector = createSelector(selectCustomer, (state: CustomerStateInterface) => state.isLoading); export const customerSelector = createSelector(selectCustomer, (state: CustomerStateInterface) => state.customer); export const errorSelector = createSelector(selectCustomer, (state: CustomerStateInterface) => state.error);
main.ts配置
bootstrapApplication( AppComponent, { providers: [ provideRouter(routes), provideStore(), provideRouterStore(), provideStoreDevtools( { maxAge: 25, logOnly: environment.production, autoPause: true } ), importProvidersFrom( BrowserModule, HttpClientModule, IonicModule.forRoot(), TranslateModule.forRoot({ loader: { provide: TranslateLoader, useFactory: (createTranslateLoader), deps: [HttpClient] } }) ) ] } ).catch(err => console.log(err));
路由配置
{ path: 'test', providers: [ provideState(customerFeatureKey, customerReducer), provideEffects(CustomerEffects) ], loadComponent: () => import('../pages/test/test.page').then(c => c.TestPage) }
问题分析与解决方案
出现错误的核心原因是:在路由级别提供Feature State时,组件初始化阶段AppStateInterface中的customer属性为undefined,而Selector直接尝试读取该属性的子字段(如isLoading),导致触发读取undefined属性的报错。Redux控制台显示数据正常切换是因为后续Action触发后Reducer会初始化该状态,但组件初始化时Selector已先执行了一次。
解决步骤:
在根Selector中添加空值兜底
修改selectCustomer,当state.customer不存在时返回Reducer的初始状态,避免后续读取子字段出错:import { initialState } from './customer.reducer'; export const selectCustomer = (state: AppStateInterface) => state.customer ?? initialState;确保AppStateInterface定义规范
检查AppStateInterface中customer属性的定义,若为可选属性需明确标注,或直接指定类型为CustomerStateInterface(而非可选),避免类型层面的undefined隐患:// 推荐写法:明确类型,无可选标识 export interface AppStateInterface { customer: CustomerStateInterface; }校验Feature Key一致性
确认路由中使用的customerFeatureKey值,与AppStateInterface中customer键名、Reducer注册的key完全一致,避免因拼写错误导致状态无法正确映射。
验证方案
修改完成后,组件初始化时Selector会返回initialState,isLoading$将获取初始值false,customer$和error$获取null,此时*ngrxLet绑定不会再触发undefined错误,后续Action触发后状态更新也能正常显示。
内容的提问来源于stack exchange,提问作者Basti-V

