combineReducers嵌套状态下,如何正确创建FeatureSelector?
问题描述
我的应用Store结构如下:
export const reducers: ActionReducerMap<State> = { auth: authReducer, settingsSlice: settingsReducer, incidentsSlice: incidentListReducer, networkStatus: networkStatusReducer, incidentSlice: incidentReducer, };
我需要为incidentSlice内部的嵌套状态创建FeatureSelector,比如获取嵌套在incidentSlice里的conferenceCall子状态中的callStatus值。但我写的代码无法正常工作:
export const selectIncidentSlice = createFeatureSelector('incidentSlice'); export const selectConferenceCall = createSelector(selectIncidentSlice, (state: any) => state.conferenceCall); export const selectConferenceCallConfig = createSelector(selectIncidentSlice, (state: any) => state.conferenceCall.conferenceCall); export const selectCallStatus = createSelector(selectConferenceCall, (state: any) => state.conferenceCall.callStatus);
相关Reducer定义:
IncidentSlice的Reducer
export interface IncidentState { currentIncident: CurrentIncidentState; statusBoard: StatusBoardState; stakeholders: StakeholderState; conferenceCall: ConferenceCallState; } export const reducer = combineReducers({ currentIncident: currentIncidentReducer, statusBoard: statusBoardReducer, stakeholders: stakeholderReducer, conferenceCall: conferenceCallReducer, });
ConferenceCall Reducer
export interface ConferenceCallState { conferenceCall: VideoCallRoomConfig; callStatus: CallStatus; } export const initialState: ConferenceCallState = { conferenceCall: conferenceCallConfigData, callStatus: CallStatus.NO_CALL, };
请问我的代码哪里出问题了?
问题分析与修正
你的Selector代码存在路径取值错误,同时不必要地使用了any类型,具体问题点和修正方案如下:
核心问题
selectConferenceCall已经获取到了incidentSlice.conferenceCall(即ConferenceCallState类型的对象),它本身直接包含callStatus属性,但你在selectCallStatus里错误地尝试通过state.conferenceCall.callStatus取值,多嵌套了一层conferenceCall。- 使用
any类型会丢失类型校验,不仅容易出错,也无法利用TypeScript的类型提示功能。
修正后的代码
// 用IncidentState约束FeatureSelector的类型,替代any export const selectIncidentSlice = createFeatureSelector<IncidentState>('incidentSlice'); // 获取incidentSlice下的conferenceCall子状态(ConferenceCallState类型) export const selectConferenceCall = createSelector( selectIncidentSlice, (state) => state.conferenceCall ); // 基于selectConferenceCall获取其中的conferenceCall配置项 export const selectConferenceCallConfig = createSelector( selectConferenceCall, (state) => state.conferenceCall ); // 直接从ConferenceCallState中取callStatus export const selectCallStatus = createSelector( selectConferenceCall, (state) => state.callStatus );
额外优化
原来的selectConferenceCallConfig直接从selectIncidentSlice取值,现在改成基于selectConferenceCall创建,既符合Selector组合复用的设计原则,也让层级关系更清晰。
内容的提问来源于stack exchange,提问作者julziemoon
相关产品推荐
相关产品推荐

