Radheya
Radheya

Reputation: 821

facing problems while checking for store data in ngrx effects before calling api

Hello I am new to NgRx application and having too many confusions over how I can solve this particular problem. I want to check the data in the store and if it is empty, only then I want to proceed with api call using NgRx effects.

After trying different things and spending whole day today I gave up and thought to get some expert guidance from here.

Below is my entire code:

analytics.effects.ts

@Injectable()
export class AnalyticsEffects {

  @Effect({dispatch: false}) loadAnalytics = this.actions$
    .pipe(
      ofType<GetAnalyticsAction>(AnalyticsTypes.GET_ANALYTICS),
      withLatestFrom(**/* cannot make this line to work */**),
      mergeMap(
        /* api call to get analytics data from server */
        () => this.analyticsService.getAnalyticsData()
          .pipe(
            map(data => {
              console.log('the data from api is...', data);
              return new GetAnalyticsAction(data)
            }),
            catchError(error => of(console.log("error in api request of analytics....")))
          )
      )
    )

  constructor(
    private actions$: Actions,
    private analyticsService: AnalyticsService,
    private store$: Store<AnalyticsState>
  ) { }
} 

analytics.action.ts

import {Action} from '@ngrx/store';
import {AnalyticsModel} from './analytics.model';
import {AnalyticsTypes} from './analytics.types';

export const GET_ANALYTICS = AnalyticsTypes.GET_ANALYTICS;

export class GetAnalyticsAction implements Action{
  readonly type = GET_ANALYTICS;
  constructor(public payload: AnalyticsModel) {
    console.log('payload sent from home is -> ', payload);
  }
}

export type Actions = GetAnalyticsAction

analytics.state.ts

import {AnalyticsModel} from './analytics.model';

export interface AnalyticsState {
  readonly analyticsModel: AnalyticsModel[];
}

analytics.reducer.ts

import {Action} from '@ngrx/store';
import {AnalyticsModel} from './analytics.model';
import * as AnalyticsAction from './../analytics/analytics.actions';

const defaultState: AnalyticsModel = {
  result: null,
}

export function reducer(state: AnalyticsModel[] = [defaultState], action: AnalyticsAction.Actions ){
  switch (action.type) {
    case AnalyticsAction.GET_ANALYTICS:
      console.log("store action type is -> ",action.type);
      console.log("store changed state is -> ",action.payload);
      return [...state, action.payload]
    default:
      return state
  }
}

mypage.component.ts

Finally the dispatcher which I am using to trigger respective actions in my component file:

  constructor(private store: Store<AnalyticsState>) {
    this.analyticsModel = store.select( state => {state.analyticsModel} );
  }

  ngOnInit() {
    this.store.dispatch(new ActionGetAnalytics.GetAnalyticsAction(this.newAnalyticsItem));
    this.newAnalyticsItem = { result: [] };
  }

What I Want

All i want is to know that how can I make use of withLatestFrom in effects.ts file above to check if the data stored in the store is empty or not before I hit the api using mergeMap. I dont want application to load api repeatedly if there is no change in data stored in the store.

What I tried

I completely exhausted myself looking for different options from official documentations and also referring to some of the same questions posted here. But nothing came to my rescue as I simply cannot understand what sort of arguments as per my code will get into 'withLatestFrom' that can help me conditionally check for the existing data.

Please help me out if you have any pointers. Thank you.

Upvotes: 1

Views: 1237

Answers (1)

timdeschryver
timdeschryver

Reputation: 15487

Check out my post Start using ngrx/effects for this.

@Effect()
shipOrder = this.actions.pipe(
  ofType<ShipOrder>(ActionTypes.ShipOrder),
  map(action => action.payload),
  concatMap(action =>
    of(action).pipe(
      withLatestFrom(this.store.pipe(select(getUserName)))
    )
  ),
  map([payload, username] => {
    ...
  })
)

Upvotes: 1

Related Questions