Creating a root store
export const increment = createAction(
    '[count] INCREMENT'
  );
  export const reset = createAction('[count] RESET');

  export const initialState = 0

  export const counterReducer = createReducer(
    initialState,
    on(increment, state => state + 1),
    on(reset, state => 0),
  );

  @NgModule({
    declarations: [],
    imports: [
      StoreModule.forRoot({ count: counterReducer })
    ],
    providers: [],
  })
  export class CounterStateModule { }
Creating actions
import { createAction, props } from '@ngrx/store';
  export const increment = createAction('[Count] INCREMENT');
With payload
export const errorAction = createAction(
    '[Error] ERROR',
    props<{ error: any }>()
  );
Dispatching action
import { Store } from '@ngrx/store';
  @Injectable()
  export class HeroDispatchers {
    // injects the store
    constructor(private store: Store<any>) {}

    incrementCounter() {
      // dispatches increment action
      this.store.dispatch(increment());
    }
  }
Creating Selectors
import {
    Store,
    createSelector,
    createFeatureSelector
  } from '@ngrx/store';
  /*
  if state is stored like
  {
    entityCache: {
      heroesState: {
        heroes: [],
        loading: false,
        error: false
      }
    }
  }
  */

  export interface EntityState {
    heroesState: {
      heroes: [],
      loading: false,
      error: false
    }
  }


  // selectors
  const getEntityState = createFeatureSelector<EntityState>(
    'entityCache'
  );

  const getHeroState = createSelector(
    getEntityState,
    (state: EntityState) => state.heroesState
  );

  const getAllHeroes = createSelector(
    getHeroState,
    (state: any) => state.heroes
  );

  const getHeroesLoading = createSelector(
    getHeroState,
    (state: any) => state.loading
  );

  @Injectable()
  export class HeroSelectors {
    constructor(private store: Store<EntityState>) { }
    // selectors$ observable can be used in html with async pipe
    heroes$ = this.store.select(getAllHeroes);
    heroState$ = this.store.select(getHeroState);
    loading$ = this.store.select(getHeroesLoading);
  }
Creating Effects

  @Injectable()
  export class AllEffects {
    // mapping to diff action
    effectName$ = createEffect(
      () => this.actions$.pipe(
        ofType(FeatureActions.actionOne),
        map(() => FeatureActions.actionTwo())
      )
    );
    // if no dispatch action after effect resolved
    effectNameWithoutDispatch$ = createEffect(
      () => this.actions$.pipe(
        ofType(FeatureActions.actionOne),
        tap(() => console.log('Action One Dispatched'))
      ),
      { dispatch: false }
      // FeatureActions.actionOne is not dispatched
    );

    getHeroes$ = createEffect(() =>
      this.actions$.pipe(
        ofType(HeroActions.getHeroes),
        switchMap(() =>
          // asyncronous call
          this.heroDataService.getHeroes().pipe(
            map(heroes => HeroActions.getHeroesSuccess({
              heroes
            })),
            catchError(error => of(
              HeroActions.getHeroesError({ error }))
            )
          )
        )
      )
    );

    addHero$ = createEffect(() =>
      this.actions$.pipe(
        ofType(HeroActions.addHero),
        concatMap(action =>
          this.heroDataService.addHero(
            action.hero
          ).pipe(
            map(
              hero =>
                HeroActions.addHeroSuccess({
                  hero
                })
            ),
            catchError(
              error =>
                of(HeroActions.addHeroError({ error }))
            )
          )
        )
      )
    );
  }

  // in ngModule
  EffectsModule.forRoot([AllEffects]),
    or
  EffectsModule.forFeature([AllEffects]),
  
Creating a sub module feature store
export const increment = createAction(
    '[count] INCREMENT'
  );
  export const reset = createAction('[count] RESET');

  export const initialState = 0

  export const counterReducer = createReducer(
    initialState,
    on(increment, state => state + 1),
    on(reset, state => 0),
  );

  @NgModule({
    declarations: [],
    imports: [
      StoreModule.forRoot({})
    ],
    providers: [],
  })
  export class AppModule { }

  @NgModule({
    declarations: [],
    imports: [
      StoreModule.forFeature('featureKey', {
        count: counterReducer
      })
    ],
    providers: [],
  })
  export class CounterStateModule { }