Search code examples
angularngrx

Ngrx effects: Can't get entities from the store or service


I'm developing an angular 8 app using ngrx (store, effects, entities, storedevtools). I'm also discovering ngrx. I followed tutorials from the official doc and everything was ok until I decided to optimize the http requests of my app.

I want to have an effect checking into the store if the entities are already loaded and if not contact my service.

I googled and found this example then inspired of it, but I have an issue https://medium.com/@haldun7/caching-http-requests-while-using-ngrx-effects-98abd50c5c78

My issue from the console browser is :

ERROR TypeError: "You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable."

This is the effect where the issue appears :

  @Effect() 
  loadAllCountries$ = this.actions$.pipe(
    ofType(fromActions.CountryActionTypes.LOAD_ALL_COUNTRIES),
    withLatestFrom(this.store.pipe(select(fromReducers.selectAllCountries))),
    switchMap((list) => { // <= this guy is a [never, Country[]] object and I don't know why :(
      if (list[1].length !== 0) {

        var temp = list[1];

        return [new fromActions.LoadCountriesSuccess( {countries: temp })];
      }
      this.service.getCountries().pipe(
        map(data => new fromActions.LoadCountriesSuccess({ countries: data })))
    })
  );

That's a quite strange because when debugging step by step, list[1] equals 0 so the else part should be executed without problems.

This is the non-optimized version of the Effect which is working perfectly

  @Effect() 
  loadAllCountries$: Observable<Action> = this.actions$.pipe(
    ofType(fromActions.CountryActionTypes.LOAD_ALL_COUNTRIES),
    switchMap(() => 
         this.service.getCountries().pipe(
         map(data => new fromActions.LoadCountriesSuccess({ countries: data })) 
      )));

Basically I have 2 questions:

  1. Does anyone know what is my code error ?
  2. Do you know why the withLatestFrom returns a [never, Country[]], I think an observable should be more helpful.

I can provide other code part (reducers, actions...) if needed, but it is very close to this example I also used to learn ngrx : https://www.concretepage.com/angular-2/ngrx/ngrx-entity-example

Many thanks for your help :)


Solution

  • You've missed return here

    return this.service.getCountries().pipe(
            map(data => new fromActions.LoadCountriesSuccess({ countries: data }))). 
    

    Therefore your switchMap doesn't return anything. In that case

    switchMap(() => 
             this.service.getCountries().pipe(
             map(data => new fromActions.LoadCountriesSuccess({ countries: data })) 
          )))
    

    Your code returns result of this.service.getCountries().. automatically, since it's one-line arrow function.