ngrx-store-simplr
TypeScript icon, indicating that this package has built-in type declarations

0.1.37 • Public • Published

Simplr

A wrapper library for @ngrx/store to use Redux concept in an easy way.


Maybe your desires:

  • like to use Redux.
  • but writing many actions and reducers is painful.
  • very painful.
  • to handle async actions is so painful.
  • finding an easy way to use Redux concept.
  • want to use Angular and RxJS.

Here Simplr comes into play.

Install

$ npm install --save @ngrx/core @ngrx/store ngrx-store-simplr

You also need to install Angular and RxJS.


Examples


Usage

Declare the app state interfaces.

// app/store/models/index.ts
 
export interface AppState {
  counter: number;
}

Create reducer and initialState to import into app.module.ts.

// app/store/reducer.ts
 
import { combineReducers } from '@ngrx/store';
import { Wrapper } from 'ngrx-store-simplr';
import { AppState } from './models';
 
const wrapper = new Wrapper<AppState>();
 
const wrappedReducers = wrapper.mergeReducersIntoWrappedReducers({
  counter: null // if you have a reducer for this key, set it here instead of null.
});
 
const rootReducer = combineReducers(wrappedReducers);
 
export function reducer(state, action) { // workaround for AoT compile
  return rootReducer(state, action);
}
 
export const initialState: AppState = {
  counter: 0
};

Edit app.module.ts in order to use Simplr.

// app/app.module.ts
 
import { StoreModule } from '@ngrx/store';
import { SimplrModule } from 'ngrx-store-simplr';
import { reducer, initialState } from './store/reducer';
 
@NgModule({
  imports: [ 
    ...,
    StoreModule.provideStore(reducer, initialState), // <== Add
    SimplrModule.forRoot(), // <== Add
  ],
})
export class AppModule { }

Create a service to dispatch to the store.

// app/services/counter.ts
 
import { Simplr } from 'ngrx-store-simplr';
import { AppState } from '../store/models';
import { initialState } from '../store/reducer';
 
@Injectable()
export class CounterService {
  constructor(
    private simplr: Simplr<AppState>,
  ) { }
 
  increment() {
    this.simplr.dispatch('counter', (state) => state + 1);
  }
 
  reset() {
    this.simplr.dispatch('counter', initialState.counter);
  }
}

Create a component to call service functions.

// app/containers/counter.ts
 
import { State } from '@ngrx/store';
import { AppState } from '../store/models';
import { CounterService } from '../services/counter';
 
@Component({
  selector: 'app-counter-container',
  template: `
    <button (click)="increment()">increment</button>
    <button (click)="reset()">reset</button>
    <pre>{{ state$ | async | json }}</pre>
  `
})
export class CounterContainerComponent {
  constructor(
    public state$: State<AppState>,
    private service: CounterService,
  ) { }
 
  increment() {
    this.service.increment();
  }
 
  reset() {
    this.service.reset();
  }
}

Done!
Did you notice that you wrote no actions and no reducers?


Demos


Details

dispatch

dispatch function allows below sync and async writings.

this.simplr.dispatch('counter', (state) => state + 1 ) // callback
// or
this.simplr.dispatch('counter', 1) // value
// or 
this.simplr.dispatch('counter', Promise.resolve((state) => state + 1 )) // callback in Promise
// or
this.simplr.dispatch('counter', Promise.resolve(1)) // value in Promise
// or
this.simplr.dispatch('counter', Observable.of((state) => state + 1 )) // callback in Observable
// or
this.simplr.dispatch('counter', Observable.of(1)) // value in Observable

dispatch function returns Observable result especially for testing.

interface Result<T, K extends keyof T> {
  action: Action,
  state: T,
  partial: T[K],
}
// getting dispatched Action
const action: Observable<Action> = 
  this.simplr
    .dispatch('counter', (state) => state + 1 )
    .map(result => result.action) // action ==> { type: 'counter @UPDATE@', payload: 1 }
 
// getting updated current whole state
const state: Observable<AppState> =
  this.simplr
    .dispatch('counter', (state) => state + 1 )
    .map(result => result.state) // state ==> { counter: 1 }
 
// getting udpated current state under the key
const partial: Observable<number> =
  this.simplr
    .dispatch('counter', (state) => state + 1 )
    .map(result => result.partial) // partial ==> 1

dispatch function allows to set some options.

// description option
const action: Observable<Action> = 
  this.simplr
    .dispatch('counter', (state) => state + 1, { desc: 'foobar' } )
    .map(result => result.action) // action ==> { type: 'counter @UPDATE@', payload: 1, desc: 'foobar' }
 
// timeout option (default: 1000 * 15)
const action: Observable<Action> = 
  this.simplr
    .dispatch('counter', Observable.of((state) => state + 1).delay(100), { timeout: 90 } )
    .map(result => result.action) // action ==> { type: 'counter @FAILED@' }
 
// retry option (default: 3)
this.simplr.dispatch('counter', /* will try this HTTP request 10 times */, { retry: 10 } )
 
// logging option ... if set be true, the result will be shown on browser console.
this.simplr.dispatch('counter', (state) => state + 1, { logging: true } )

Package Sidebar

Install

npm i ngrx-store-simplr

Weekly Downloads

5

Version

0.1.37

License

MIT

Last publish

Collaborators

  • ovrmrw