How to simplify NgRx effects? Only difference the service method they call-

275 views Asked by At

I have got the following code from an NgRx effects file:

  registerUser$: Observable<Action> = createEffect(() =>
    this.actions$.pipe(
      ofType(AuthStoreActions.registerUser),
      switchMap(action => {
        return this.authService.registerWithEmailAndPassword(action.userCredentials).pipe(
          map(() => AuthStoreActions.authSuccess({ navigateTo: "authentication/restaurant" })),
          catchError(error => of(AuthStoreActions.setError({ error })))
        );
      })
    )
  );
  loginUser$: Observable<Action> = createEffect(() =>
    this.actions$.pipe(
      ofType(AuthStoreActions.loginUser),
      switchMap(action => {
        return this.authService.loginWithEmailAndPassword(action.userCredentials).pipe(
          map(() => AuthStoreActions.authSuccess({ navigateTo: "authentication/restaurant" })),
          catchError(error => of(AuthStoreActions.setError({ error })))
        );
      })
    )
  );

After the service call both are doing the same thing. How could eleminate the repeatness? I have got an other sibling effects aswell which does more after receiving the response from the server than this example, but apart from the method they call, they are doing the same thing.

2

There are 2 answers

2
Thomas Ruble On BEST ANSWER

With the pipe function, you can bottle up those auth store operators in one.

The power of function composition!

import { pipe } from "rxjs";

const handleAuth = pipe(
  map(() => AuthStoreActions.authSuccess({ navigateTo: "authentication/restaurant" })),
  catchError(error => of(AuthStoreActions.setError({ error }))));

loginUser$: Observable<Action> = createEffect(() =>
  this.actions$.pipe(
    ofType(AuthStoreActions.loginUser),
    switchMap(action => this.authService.loginWithEmailAndPassword(action.userCredentials).pipe(handleAuth)));

registerUser$: Observable<Action> = createEffect(() =>
    this.actions$.pipe(
      ofType(AuthStoreActions.registerUser),
      switchMap(action => this.authService.registerWithEmailAndPassword(action.userCredentials).pipe(handleAuth)));
1
timdeschryver On

I would say, keep it as it is instead wanting to reduce some LOC

The as is solution is more readable and easier to react to change, in comparison to the following:

  loginUser$: Observable<Action> = createEffect(() =>
    this.actions$.pipe(
      ofType(AuthStoreActions.loginUser, AuthStoreActions.registerUser),
      switchMap(action => {
        return this.authService[action.serviceMethod](action.userCredentials).pipe(
          map(() => AuthStoreActions.authSuccess({ navigateTo: "authentication/restaurant" })),
          catchError(error => of(AuthStoreActions.setError({ error })))
        );
      })
    )
  );