J.Doe
J.Doe

Reputation: 341

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

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.

Upvotes: 1

Views: 287

Answers (2)

timdeschryver
timdeschryver

Reputation: 15507

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 })))
        );
      })
    )
  );

Upvotes: 0

Thomas Ruble
Thomas Ruble

Reputation: 952

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)));

Upvotes: 2

Related Questions