ngrx-command-reducer
A command-style redux reducer for Angular and ngrx/store with type checking for actions and their payloads.
- Reducers essentially become a clean map of actions to pure function commands.
- The highly-testable commands encapsulate your business logic and return state.
- Actions are class based (no more magic strings!) and have typed payloads.
- State and action payloads are type checked against the commands you map them to.
- Highly testable
Installation
$ npm install ngrx-command-reducer
Example usage
Reducer
The command reducer will ensure that an action can only be mapped to a command expecting a payload of the same type.
;;;// more imports etc... const DEFAULT_STATE: CurrentUser = isLoading: false user: null error: null; const currentUserReducer: ActionReducer<CurrentUser> = <CurrentUser>DEFAULT_STATE ;
Action
;; implements Action /** * Assigning a meaningful value to the `type` property is not * mandatory. It's only required for guaranteed compatibility with any * third-party ngrx tools not using an `instanceof` check for actions. */ type: string = 'LoginAction'; { // }
ReducerCommand
;; : CurrentUser { state = Object; stateisLoading = true; stateerror = null; // Access payload.username or payload.password if you need to return state;};
Effects
If using @ngrx/effects, you can respond to a typed action by replacing the .ofType
operator with .filter
:
@ login$ = thisactions$
Dispatch
const username = 'missfoo';const password = 'ilikebar'; // The LoginAction payload is defined by the LoginParams interfacethisstore$;
Testing
ReducerCommands
ReducerCommands
are extremely easy to test, as they should be implemented as pure functions.
- Import the pure function into your test spec
- Pass a mock state and payload when manually executing the reducer command
- Assert on the returned state
Reducers
You can also test that the CommandReducer
is executing the correct command functions when specific actions are
dispatched. Simply mock your commands with useMockCommand()
like so:
foo.reducer.ts:
const fooReducer: ActionReducer<Foo> = <Foo>DEFAULT_STATE ;
foo.reducer.spec.ts — an example using jasmine:
const myMockCommand = jasmine;fooReducer; // ... dispatch AddBarAction to store ... ;