[NgRx] NgRx Data Fetching Solution - How to Load Data Only If Needed

Posted answer1215

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NgRx] NgRx Data Fetching Solution - How to Load Data Only If Needed相关的知识,希望对你有一定的参考价值。

We have a reoslver, which everytime we want visit ‘/courses‘ route, it will be triggered, then api will be called, data will be loaded.

import  Injectable  from "@angular/core";
import 
  Resolve,
  ActivatedRouteSnapshot,
  RouterStateSnapshot
 from "@angular/router";
import  Observable  from "rxjs";
import  Store  from "@ngrx/store";
import  AppState  from "../reducers";
import  CoursesAction  from "./actions-types";
import  tap, first, finalize  from "rxjs/operators";
import  adapter  from "./reducers/courses.reducers";

@Injectable()
export class CoursesResolver implements Resolve<any> 
  loading = false;
  constructor(private store: Store<AppState>) 

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> 
    return this.store.pipe(
      tap(() => 
        if (!this.loading) 
          this.loading = true;
          this.store.dispatch(CoursesAction.loadAllCourse());
        
      ),
      // this resolve need to complete, so we can use first()
      first(),
      finalize(() => (this.loading = false))
    );
  

 

So how to prevent reload the data if we have already loaded the data once?

Add one prop into state: ‘allCoursesLoaded‘

import  Course, compareCourses  from "../model/course";
import  EntityState, createEntityAdapter  from "@ngrx/entity";
import  createReducer, on  from "@ngrx/store";
import  CoursesAction  from "../actions-types";
/*
export interface CoursesState 
  entities:  [key: number]: Course ;
  ids: number[];
*/

export interface CoursesState extends EntityState<Course> 
  /**Extend the entity here */
  allCoursesLoaded: boolean;


export const adapter = createEntityAdapter<Course>(
  sortComparer: compareCourses
  // selectId: course => course.id // NgRx use ‘id‘ by default
);

export const initCoursesState = adapter.getInitialState(
  allCoursesLoaded: false
);

export const coursesReducer = createReducer(
  initCoursesState,
  on(CoursesAction.allCoursesLoaded, (state, action) =>
    adapter.addAll(action.courses,  ...state, allCoursesLoaded: true )
  )
);

export const  selectAll  = adapter.getSelectors();

Now we can modify the resolver:

import  Injectable  from "@angular/core";
import 
  Resolve,
  ActivatedRouteSnapshot,
  RouterStateSnapshot
 from "@angular/router";
import  Observable  from "rxjs";
import  Store, select  from "@ngrx/store";
import  AppState  from "../reducers";
import  CoursesAction  from "./actions-types";
import  tap, first, finalize, filter  from "rxjs/operators";
import  adapter  from "./reducers/courses.reducers";
import  selectAllCoursesLoaded  from "./courses.selectors";

@Injectable()
export class CoursesResolver implements Resolve<any> 
  loading = false;
  constructor(private store: Store<AppState>) 

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<any> 
    return this.store.pipe(
      select(selectAllCoursesLoaded),
      tap(courseLoaded => 
        if (!this.loading && !courseLoaded) 
          this.loading = true;
          this.store.dispatch(CoursesAction.loadAllCourse());
        
      ),
      // this resolve need to complete, so we can use first()
      filter(courseLoaded => courseLoaded),
      first(),
      finalize(() => (this.loading = false))
    );
  

 

以上是关于[NgRx] NgRx Data Fetching Solution - How to Load Data Only If Needed的主要内容,如果未能解决你的问题,请参考以下文章

Ngrx 相对于 Observable Data Services 架构的优势? [关闭]

ngrx 测试效果动作失败

[NgRx] NgRx Entity Adapter Configuration - Understanding sortComparer and selectId

安装@ngrx/store 时如何清除错误?

如何使用 ngrx-router-store 在 ngrx 效果中获取路由参数?

NgRx @Effect 与 createEffect