Platform: ofAction operator

Created on 8 Feb 2018  路  6Comments  路  Source: ngrx/platform

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[X] Feature request
[ ] Documentation issue or request

What is the current behavior?


In effects we regularly use this.actions$.ofType<DoThatAction>(doThatActionTypes.DO_THAT)

Expected behavior:


I would like to propose ofAction function which would change all that verbosity into

this.actions$.ofAction(DoThatAction)

Resulting in effects not using constant strings

// ...
@Effect()
    Load$ = this.update$.pipe(
        ofAction(Load),
        switchMap(() => this.myService.getAll()),
        map(res => new LoadSuccess(res))
    );
// ...

Other information:

As seen in quite promising https://github.com/amcdnl/ngrx-actions repository (well I inlined ActionType here for brevity).

Also there might be some other joint best practices interests with ngrx-actions fellows if you haven't had time to see what they've been up to.

import { Action } from '@ngrx/store';
import { filter } from 'rxjs/operators';
import { OperatorFunction } from 'rxjs/interfaces';

export type ActionType<T extends Action = Action> = { new (...args: any[]): T };

export function ofAction<T extends Action>(allowedType: ActionType<T>): OperatorFunction<Action, T>;
export function ofAction<T extends Action>(...allowedTypes: ActionType[]): OperatorFunction<Action, T>;
export function ofAction(...allowedTypes: ActionType[]): OperatorFunction<Action, Action> {
  const allowedMap = {};
  allowedTypes.forEach(klass => (allowedMap[new klass().type] = true));
  return filter((action: Action) => {
    return allowedMap[action.type];
  });
}

Most helpful comment

Sorry, but this won't be added to @ngrx/effects. It would either rely on us having to instantiate a class to infer the action type or use the instanceof operator to determine the actions. Both of these break a core principle of NgRx and Redux: Actions should be serializable in both directions. Consider how this would work if you were receiving a stream of actions over a websocket connection or a PWA that stores actions in local storage when offline (hint: it wouldn't work).

Furthermore, we will be able to strongly type the ofType operator starting with TypeScript 2.8.

All 6 comments

you wont have to use type cast with this https://github.com/ngrx-utils/ngrx-utils but still have nice type inference ^^. It also makes use of _instanceof_ instead of _new Action_ so I think it is a more performant approach.

Sorry, but this won't be added to @ngrx/effects. It would either rely on us having to instantiate a class to infer the action type or use the instanceof operator to determine the actions. Both of these break a core principle of NgRx and Redux: Actions should be serializable in both directions. Consider how this would work if you were receiving a stream of actions over a websocket connection or a PWA that stores actions in local storage when offline (hint: it wouldn't work).

Furthermore, we will be able to strongly type the ofType operator starting with TypeScript 2.8.

@MikeRyanDev I've explained this principle to people (mostly off-line) many times, but have received pushback since I've so far been unable to point somewhere in the documentation that states this. What do you think of some bit of documentation somewhere that explains this?

@kylecordes https://redux.js.org/docs/faq/Actions.html

Agree with @MikeRyanDev, though it kill my DX with tons of boilerplate.

@kylecordes I'd love to see some documentation for this!

I second that and think that a "core principles" section in the docs on store would be very valuable.

Was this page helpful?
0 / 5 - 0 ratings