[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 Entity Adapter Configuration - Understanding sortComparer and selectId