Query module based on the @ngrx/store package.
yarn add @ngsm/query
or npm i @ngsm/query --save
Library requires @ngrx/store
module.
State (for example homepage.state.ts
):
import { queryReducer } from '@ngsm/query';
import { HomepageApiResponseDto } from 'your-api-dto.interfaces.ts';
export interface HomepageQueryState {
getHomepageApiQuery?: Query<HomepageApiResponseDto>;
}
export const HOMEPAGE_QUERY_KEY = 'homepageQuery';
export interface HomepagePartialState {
readonly [HOMEPAGE_QUERY_KEY]: HomepageQueryState;
// Your feature states, for example:
// readonly [HOMEPAGE_FEATURE_KEY]: HomepageState;
}
Reducer (for example homepage.reducer.ts
):
import { Action } from '@ngrx/store';
import { HomepageQueryState } from './homepage.state';
...
export function homepageQueryReducer(state: HomepageQueryState | undefined, action: Action) {
return queryReducer(state, action);
}
Selectors (for example homepage.selectors.ts
):
import { createFeatureSelector, createSelector } from '@ngrx/store';
export const homepageQueryState = createFeatureSelector<HomepagePartialState, HomepageQueryState>(HOMEPAGE_QUERY_KEY);
export const getHomepageApiQuery = createSelector(
homepageQueryState,
(state: HomepageQueryState) => state.getHomepageApiQuery
);
State module (for example homepage-state.module.ts
):
import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { HomapageEffects } from './homepage.effects';
import { HomapageFacade } from './homepage.facade';
import { homepageQueryReducer, homepageReducer } from './homepage.reducer';
import { HOMEPAGE_QUERY_KEY } from './homepage.state';
@NgModule({
imports: [
StoreModule.forFeature(HOMEPAGE_QUERY_KEY, homepageQueryReducer),
EffectsModule.forFeature([HomapageEffects]),
],
providers: [HomapageFacade]
})
export class HomapageStateModule {}
Effects (for example homepage.effects.ts
):
...
getHomepageApi$ = createEffect(() =>
this.actions$.pipe(
ofType(HomepageActions.getHomepageApi),
mergeMap(() => concat(
// run inProgress action
of(QueryActions.inProgress({ query: HomepageQuery.getHomepageApiQuery })),
this.homepageRepository
.getHomepageApi()
.pipe(
mergeMap((response) => [
// run success action
QueryActions.success({ query: HomepageQuery.getHomepageApiQuery, response }),
]),
catchError(error => [
// run failure action
QueryActions.failure({ query: HomepageQuery.getHomepageApiQuery, error }),
])
)
))
)
);
...
Facade (for example homepage.facade.ts
):
...
@Injectable()
export class HomepageFacade {
getHomepageQuery$ = this.store.pipe(select(HomepageSelectors.getHomepageQuery));
loader$ = isQueryInProgress$([
this.getHomepageQuery$,
// add all feature queries
...,
]);
constructor(private store: Store<HomepagePartialState>) {}
dispatch(action: Action) {
this.store.dispatch(action);
}
}
Sebastian Musiał |