Search code examples
angularasp.net-mvctypescriptrxjsngrx

How to get only latest data from ngrx/store on reload api call


I am using ngrx/store and ngrx/effects in my angular app.

My issue is that selector in reducer returns old as well as new value after api call from feature state. Below is my code:

reducer.ts

case PortfolioActions.PortActionTypes.LOAD_SUCCESS_TRADE_NAV:
    return {
        ...state,
        navData: action.payload,
        isLoadingNav: false
    };

export const getNavData = createSelector(
    getPortfolioFeatureState,
    state => state.navData
);

In effects.ts

@Effect()
    loadNav$: Observable<Action> = this.action$.pipe(
        ofType<fromPortfolio.LoadTradeNAV>(fromPortfolio.PortActionTypes.LOAD_TRADE_NAV),
        switchMap((action) => this.dashSvc.getNetAssetValue(action.payload.key,action.payload.currency)
            .pipe(
                map((data) => {
                    return new fromPortfolio.LoadSuccessTradeNAV(data)
                })
            )
        )
    );

In compoenent.ts

reload(){
    this.portStore.dispatch(new portfolioActions.LoadTradeNAV(this.searchParam));

    this.portStore.pipe(
    select(fromPortfolio.getNavData),
    filter(f => !!f),
    takeWhile(() => this.componentActive))
    .subscribe((fmtRes) => {
        console.log(fmtRes) //Issue here
        this.data = fmtRes;
    })
}

In component when I call reload() method, in subscribe() I always get the old data and then later on new data after the api call is done.

My question is how can I get the store data only after the api load success is done


Solution

  • You can use withLatestFrom

    @Effect()
        loadNav$: Observable<Action> = this.action$.pipe(
            ofType<fromPortfolio.LoadTradeNAV>(fromPortfolio.PortActionTypes.LOAD_TRADE_NAV),
            withLatestFrom(this.store.pipe(select(selector))), // pass in your selector here in select()
            switchMap((action) => this.dashSvc.getNetAssetValue(action.payload.key,action.payload.currency)
                .pipe(
                    map((data) => {
                        return new fromPortfolio.LoadSuccessTradeNAV(data)
                    })
                )
            )
        );
    

    Update. I would recommend you put this code in ngOnInit() hook

    ngOnInit() {
        this.portStore.pipe(
        select(fromPortfolio.getNavData),
        filter(f => !!f),
        takeWhile(() => this.componentActive))
        .subscribe((fmtRes) => {
            console.log(fmtRes) //Issue here
            this.data = fmtRes;
        })
    }