Angular 5 ngrx Effect no exported member 'ofType'

tprieboj picture tprieboj · Jan 21, 2018 · Viewed 7.2k times · Source

I am trying to implement Effects for my ngrx state manager. Currently I am using Angular v5.2.1, ngrx v4.1.1 and rxjs v5.5.6. I tried "older" proach for example

@Effect() login$: Observable<Action> = this.actions$.ofType('LOGIN')
.mergeMap(action =>
  this.http.post('/auth', action.payload)
    // If successful, dispatch success action with result
    .map(data => ({ type: 'LOGIN_SUCCESS', payload: data }))
    // If request fails, dispatch failed action
    .catch(() => of({ type: 'LOGIN_FAILED' }))
);

But I was getting an error Property 'mergeMap' does not exist on type 'Actions<Action>'. So I used new pipe method. The problem is when I try to import ofType operator

// ...
import { Action } from '@ngrx/store';
import { Effect, Actions, ofType } from '@ngrx/effects';

import { map, mergeMap, catchError } from 'rxjs/operators';
import { of } from 'rxjs/observable/of';

@Injectable()
export class WifiEffects {

  @Effect()
  getWifiData: Observable<Action> = this.actions$.pipe(
    ofType(WifiTypes.getWifiNetworks),
    mergeMap((action: GetWifiNetworks) =>
      this.mapService.getWifiNetworks().pipe(
        map((data: WifiNetworks) => new GetWifiNetworksSucc(data)),
        catchError(() => of(new GetWifiNetworksErr()))
      )),
  );

  constructor (
    private actions$: Actions,
    private mapService: GoogleMapDataService
  ) {}

}

Iam getting an error Module '".../node_modules/@ngrx/effects/effects"' has no exported member 'ofType'. Any ideas?

Answer

Richard Matsen picture Richard Matsen · Jan 21, 2018

Looking at @ngrx/effects API, there's no sign that this library has implemented a lettable version of ofType, so your second implementation won't work (at least not with ofType inside the pipe).

Your first implementation is just missing an import for mergeMap

import 'rxjs/add/observable/mergeMap';

and probably map and catch as well

import 'rxjs/add/observable/map';
import 'rxjs/add/observable/catch';

If you want to use ofType with pipe, this will probably work

@Effect()
getWifiData: Observable<Action> = 
  this.actions$.ofType(WifiTypes.getWifiNetworks)
    .pipe(
      mergeMap((action: GetWifiNetworks) =>
      ...

since ofType() returns an Observable which has .pipe already added to it's prototype.


Footnote

After looking through the source code on github (as at 22 Jan 2018), I found an export for lettable ofType here platform/modules/effects/src/index.ts.

But upon installing with @ngrx/effects@latest (which gives me ver 4.1.1) I can't see this export reference under the installed node_modules folder.

In my component, I can't use import { ofType } from '@ngrx/effects'; either.