欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

13 - NgRx Effects router navigate 有大用 有大大用

13 - NgRx Effects

In this section we examine adding effects

1. Add an Auth Effects

libs/auth/src/lib/+state/auth.effects.ts
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { AuthActionTypes } from './auth.actions';
import { mergeMap, map, catchError, tap } from 'rxjs/operators';
import { of } from 'rxjs';
import { AuthService } from './../services/auth/auth.service';
import * as authActions from './auth.actions';
import { User } from '@demo-app/data-models';
@Injectable()
export class AuthEffects {
 @Effect()
 login$ = this.actions$.pipe(
   ofType(AuthActionTypes.Login),
   mergeMap((action: authActions.Login) =>
     this.authService
       .login(action.payload)
       .pipe(
         map((user: User) => new authActions.LoginSuccess(user)),
         catchError(error => of(new authActions.LoginFail(error)))
       )
   )
 );
 constructor(
   private actions$: Actions,
   private authService: AuthService
 ) {}
}

2. Add reducer code

libs/auth/src/lib/+state/auth.reducer.ts
import { AuthActions, AuthActionTypes } from './auth.actions';
import { User } from '@demo-app/data-models';
export interface AuthData {
 loading: boolean;
 user: User;
 error: '';
}
export interface AuthState {
 readonly auth: AuthData;
}
export const initialState: AuthData = {
 error: '',
 user: null,
 loading: false
};
export function authReducer(
 state = initialState,
 action: AuthActions
): AuthData {
 switch (action.type) {
   case AuthActionTypes.Login:
     return { ...state, loading: true };
   case AuthActionTypes.LoginSuccess: {
     return { ...state, user: action.payload, loading: false };
   }
   case AuthActionTypes.LoginFail: {
     return { ...state, user: null, loading: false };
   }
   default:
     return state;
 }
}

3. Update LoginComponent to dispatch an action

libs/auth/src/lib/containers/login/login.component.ts
import { Component, ChangeDetectionStrategy, } from '@angular/core';
import { Authenticate } from '@demo-app/data-models';
import { AuthState } from './../../+state/auth.reducer';
import { Store } from '@ngrx/store';
import * as authActions from './../../+state/auth.actions';
@Component({
 selector: 'app-login',
 templateUrl: './login.component.html',
 styleUrls: ['./login.component.scss'],
 changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoginComponent {
 constructor(
   private store: Store<AuthState>) { }
 login(authenticate: Authenticate) {
  this.store.dispatch(new authActions.Login(authenticate));
 }
}

4. Add new Effect action to navigate on LoginSuccess

  • Add new effect to manage routing

You can read more about routing with actions here https://github.com/ngrx/platform/blob/master/docs/router-store/api.md#navigation-actions.

libs/auth/src/lib/+state/auth.effects.ts
import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { AuthActionTypes } from './auth.actions';
import { mergeMap, map, catchError, tap } from 'rxjs/operators';
import { of } from 'rxjs';
import { AuthService } from './../services/auth/auth.service';
import * as authActions from './auth.actions';
import { User } from '@demo-app/data-models';
import { Router } from '@angular/router';
@Injectable()
export class AuthEffects {
 @Effect()
 login$ = this.actions$.pipe(
   ofType(AuthActionTypes.Login),
   mergeMap((action: authActions.Login) =>
     this.authService
       .login(action.payload)
       .pipe(
         map((user: User) => new authActions.LoginSuccess(user)),
         catchError(error => of(new authActions.LoginFail(error)))
       )
   )
 );
 @Effect({ dispatch: false })
 navigateToProfile$ = this.actions$.pipe(
   ofType(AuthActionTypes.LoginSuccess),
   map((action: authActions.LoginSuccess) => action.payload),
   tap(() => this.router.navigate([`/products`]))
 );
 constructor(
   private actions$: Actions,
   private authService: AuthService,
   private router: Router
 ) {}
}

5. Export state references in index.ts

libs/auth/index.ts
export * from './lib/auth.module';
export { AuthService } from './lib/services/auth/auth.service';
export { AuthGuard } from './lib/guards/auth/auth.guard';
export { AuthState } from './lib/+state/auth.reducer';

6. Update AuthGuard to use the store

import { Injectable } from '@angular/core';
import {
 CanActivate,
 ActivatedRouteSnapshot,
 RouterStateSnapshot,
 Router
} from '@angular/router';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { AuthState } from '@demo-app/auth';
import { Store, select } from '@ngrx/store';
@Injectable({
 providedIn: 'root'
})
export class AuthGuard implements CanActivate {
 constructor(private router: Router, private store: Store<AuthState>) { }
 canActivate(
   next: ActivatedRouteSnapshot,
   routerState: RouterStateSnapshot
 ): Observable<boolean> {
   return this.store.pipe(select((state) => state.auth.user),
     map(user => {
       if (user) {
         return true;
       } else {
         this.router.navigate([`/auth/login`]);
         return false;
       }
     })
   );
 }
}

7. On load check local storage and dispatch a LoginSuccess action

apps/customer-portal/src/app/app.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { AuthState } from '@demo-app/auth';
import { LoginSuccess } from '@demo-app/auth/src/lib/+state/auth.actions';
@Component({
 selector: 'app-root',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.scss']
})
export class AppComponent {
 title = 'app';
 constructor(private store: Store<AuthState>){
     const user = JSON.parse(localStorage.getItem('user'));
     if(user) {
       this.store.dispatch(new LoginSuccess(user))
     }
   };
}



来自  https://duncanhunter.gitbook.io/enterprise-angular-applications-with-ngrx-and-nx/13-ngrx-effects

普通分类: