Saturday, July 22, 2017
Ngrx Platform
I've used ngrx/store and ngrx/effects for a while, and like the pattern. The new version has been released, and here are some of the changes I had to make in my code.
Pre v4 you built your reducers as follows, passing an object with
stateslice: reducerfunction.
With the new version, don't use combineReducers. I was running into the situation where the reducers weren't being initialized and the state was null.
Now you create your object of reducers:
export const reducer: ActionReducerMap = {
contactprimary: fromPrimary.reducer
contactselection: fromSelectionList.reducer
contactlist: undoable(fromContactList.reducer),
relations: relationUndoable(fromRelations.reducer),...
and in your app.module imports: [] section
The second big change is the Action type has been redefined.
This breaks any of your code where you use action.payload. To fix it you have to define Action in each reducer. First define your action classes.
Note that the payload has a type in each one, and it is the same. You can call it whatever you like, or have multiple properties. The type Actions is exported.
Then in your reducer.
In this reducer, action is of the type defined in your action classes. The same action needs to be defined in the Effects as well.
This requires refactoring much of your reducers and effects. If you have different payloads for each of your defined action classes, lots of changes.
The advantage is strict typing of the data being passed around. It caught a couple minor flaws in my code, and I will be rewriting some reducers to take advantage of the added protection.
Otherwise it all works. The documentation is very helpful, especially with the specific initialization requirements.
I will update this blog after I have refactored the feature module reducers. There are also some improvements in the way selectors can be grouped.
Pre v4 you built your reducers as follows, passing an object with
stateslice: reducerfunction.
const productionReducer = combineReducers(reducers); export function reducers(state: any, action: any) { return productionReducer(state, action);}
With the new version, don't use combineReducers. I was running into the situation where the reducers weren't being initialized and the state was null.
Now you create your object of reducers:
export const reducer: ActionReducerMap
contactprimary: fromPrimary.reducer
contactselection: fromSelectionList.reducer
contactlist: undoable(fromContactList.reducer),
relations: relationUndoable(fromRelations.reducer),...
and in your app.module imports: [] section
StoreModule.forRoot(reducer),
The second big change is the Action type has been redefined.
export interface Action { type: string; }
This breaks any of your code where you use action.payload. To fix it you have to define Action in each reducer. First define your action classes.
import {Action} from "@ngrx/store";
import {PrintItem} from "../../../models/print.model"; export const ADD_TO_QUEUE = '[Printing] Add to queue';
export const REMOVE_FROM_QUEUE = '[Printing] Remove from queue';
export const MARK_STATUS = '[Printing] mark status'; export class Print implements Action { type = ADD_TO_QUEUE;
constructor(public payload: PrintItem) {} } export class PrintDone implements Action { type = REMOVE_FROM_QUEUE;
constructor(public payload: PrintItem) {} } export class PrintStatus implements Action { type = MARK_STATUS;
constructor(public payload: PrintItem) {} } export type Actions = Print | PrintStatus | PrintDone;
Note that the payload has a type in each one, and it is the same. You can call it whatever you like, or have multiple properties. The type Actions is exported.
Then in your reducer.
import {PrintState} from "../../../models/print.model";import {ActionReducer} from "@ngrx/store";import * as printingActionTypes from "../actions/printing.actions"; export type Action = printingActionTypes.Actions; const initialState: PrintState = { queue: [] }; export const reducer: ActionReducer= (
state = initialState, action: Action) => { switch (action.type) {
....
In this reducer, action is of the type defined in your action classes. The same action needs to be defined in the Effects as well.
This requires refactoring much of your reducers and effects. If you have different payloads for each of your defined action classes, lots of changes.
The advantage is strict typing of the data being passed around. It caught a couple minor flaws in my code, and I will be rewriting some reducers to take advantage of the added protection.
Otherwise it all works. The documentation is very helpful, especially with the specific initialization requirements.
I will update this blog after I have refactored the feature module reducers. There are also some improvements in the way selectors can be grouped.
Subscribe to Posts [Atom]