DEV Community

Discussion on: NgRx Tips I Needed in the Beginning

Collapse
 
markostanimirovic profile image
Marko Stanimirović This is Angular

Hi Tim!

You can do something like this:

export type LoadState = 'INIT' | 'LOADING' | 'LOADED' | { errorMsg: string };

// songs.reducer.ts

interface State {
  songs: Song[];
  loadState: LoadState;
}

const initialState: State = {
  songs: [],
  loadState: 'INIT',
};

export const reducer = createReducer(
  initialState,
  on(SongsPageActions.opened, (state) => state.loadState === 'LOADED'
    ? state
    : { ...state, loadState: 'LOADING' }
  ),
  on(SongsApiActions.songsLoadedSuccess, (state, { songs }) => ({
    ...state,
    songs,
    loadState: 'LOADED',
  }),
  on(SongsApiActions.songsLoadedFailure, (state, { errorMsg }) => ({
    ...state,
    loadState: { errorMsg },
  })
);

// songs-api.effects.ts

readonly loadSongsIfNotLoaded$ = createEffect(() => {
  return this.actions$.pipe(
    ofType(SongsPageActions.opened),
    concatLatestFrom(() => this.store.select(songsSelectors.selectLoadState)),
    filter(([, loadState]) => loadState !== 'LOADED'),
    exhaustMap(() => {
      return this.songsService.loadSongs().pipe(
        map((songs) => SongsApiActions.songsLoadedSuccess({ songs })),
        catchError((error) =>
          of(SongsApiActions.songsLoadedFailure({ errorMsg: error.message }))
        )
      );
    })
  );
});
Enter fullscreen mode Exit fullscreen mode

Additionaly, if you have a complex condition that is repeated in the effect as well as in the reducer, you can move it to a helper function and reuse it in both places.

Thread Thread
 
thardy profile image
Tim Hardy

Thanks a lot! I'm going to try this. I like the idea of making the condition something reusable. I also have come to the conclusion that I don't actually need these conditions as often as I thought. In reality, I rarely stop the loading of something because it's already loaded. The actions that cause something to load almost always cause them to load. On the rare occasion I really need a conditional load, this sounds like a clean way to handle it.