Search code examples
angularngrx

Hierarchical store organization


I have a problem with figuring out how to compose hierarchical store in Angular. I would like to multiple reducers which work on particular part of the application.

Here is a description: this is a HR application. I have module of talent (employee) whose data are split in five sections: expertise, education, backgroundCheck, location and salary, job preserences.

Each section contains fairly complex logic to satisfy business expectations. We are updating some cases for the market and we need to share data between components on multiple part.

So start with the root module I have defined root state for the talent module

I have tried using combineReducers like described in these post: Angular 6 / NGRX Combine Reducers

So start with the root module I have defined root state for the talent module

export interface ITalentState {
    profile: IProfileState;
}

here is the reducer for talent state

export function talentReducer(state = talentInitialState, action: TalentActions): ITalentState {
    switch(action.type) {
        case TalentActionTypes.SetProfile:
            return {
                ...state,
                profile: action.profileData 
            }
        default: return state;
    }
}

ProfileState is defined like this

export interface IProfileState {
    expertiseState: IExpertiseState;
}

Here is expertise section:

export interface IExpertiseState {
    expertiseQuestions: ExpertiseQuestions;
    error: string;
}

Expertise section

function expertiseReducer(state, action)
    switch(action.type) {
        case ExpertiseActionsTypes.LoadFailed:
            return {
                ...state,
                expertiseQuestions: new ExpertiseQuestions(),
                error: action.message
            }
        case ExpertiseActionsTypes.LoadSuccess:
            return {
                ...state,
                expertiseQuestions: action.questions,
                error: ''
            }
        default: return state;
    }
}

I expect there is a way to achieve store granulation and to split reducers so they are more manageabale, but only thing I see in the debugger is that the expertise store methods are called but reducer is never called and values are not updated in the store.


Solution

  • I figured it out. Basically, to use this kind of store, we need to compose one reducer per feature (depends on the granulation) and then expose it as one public reducer Here is the solution:

    export interface TalentState {
    expertise: fromExpertise.ExpertiseState
    }
    
    export const reducers: ActionReducerMap<TalentState>  = {
    expertise: fromExpertise.expertiseReducer
    }
    
    export const getTalentState = createFeatureSelector<TalentState>('talent')