redux-observable-decorator

v1.0.0
Decorators for Redux Observable

CircleCI npm version npm downloads

redux-observable-decorator

Decorators for Redux Observable

When using Redux with Angular with angular-redux/store and redux-observable, it's common to create your epics as an injectable class, and when configuring the store - creating an epic middleware for each one, or using combineEpics:

@Injectable()
export class SomeEpics {
    epicOne = (action$) => action$.ofType('PING').pipe(mapTo({type: 'PONG'}));
    epicTwo = (action$) => action$.ofType('ACTION_IN').pipe(mapTo({type: 'ACTION_OUT'}));
}

@NgModule({

})
export class AppModule {
    constructor(ngRedux: NgRedux, someEpics: SomeEpics) {
        let epics = combineEpics(
            someEpics.epicOne,
            someEpics.epicTwo
        );
        let epicMiddleware = createEpicMidleware();

        ngRedux.configureStore(reducer,[epicMiddleware]);
        epicMiddleware.run(epics);

        // or

        let epicOne = createMiddleware(someEpics.epicOne);
        let epicTwo = createMiddleware(someEpics.epicTwo);

        ngRedux.configureStore(reducer,[epicOne, epicTwo]);
    }
}

This decorator is intended to make it easier to mark which properties / methods in a class are Epics to simplify creating the epic middleware for your application.

import { Epic } from 'redux-observable-decorator';

@Injectable()
export class SomeEpics {
    @Epic() epicOne = (action$) => action$.ofType('PING').pipe(mapTo({type: 'PONG'}));
    @Epic() epicTwo = (action$) => action$.ofType('ACTION_IN').pipe(mapTo({type: 'ACTION_OUT'}));
}
import { combineDecoratedEpics } from 'redux-observable-decorator';
import { createEpicMiddleware } from 'redux-observable';

@NgModule({

})
export class AppModule {
    constructor(ngRedux:NgRedux, someEpics:SomeEpics) {
        let epics = combineDecoratedEpics(someEpics);
        const epicMiddleware = createEpicMiddleware();

        ngRedux.configureStore(reducer,[epicMiddleware]);
        epicMiddleware.run(epics);
    }
}

This can be used with vanilla redux also - as seen in the unit tests...

class Test {
    @Epic() epic = (action$) => action$.ofType('TEST_IN').pipe(mapTo({ type: 'TEST_OUT' }));
}

const reducer = (state = [], action) => state.concat(action);
const epics = new Test();
const epicMiddleware = createEpicMiddleware(epics);
const store = createStore(reducer, applyMiddleware(epicMiddleware));
epicMiddleware.run(combineDecoratedEpics(epics));

Inspiration

The @Effect decorator from ngrx/effects

Todo

  • Better docs
  • Publish on NPM
  • Improve tests
  • Get test coverage working
  • Some Anglar 2 / integration tests
  • Example App
  • Strategy for lazy loading epics (to support code-splitting)?

Metadata

  • MIT
  • Whatever
  • Evan Schultz
  • released 1/31/2017

Downloads

Maintainers