ngrx store Introduction - Tuong-Nguyen/Angular-D3-Cometd GitHub Wiki
- Store
Rx.Observable
Rx.Observer
-
Rx.BehaviorSubject = Rx.Observable + Rx.Observer
(composition, variant ofRx.Subject
)
dispatcher, reducer and state based on Rx.BehaviorSubject
- Reducer: similar as reducer in Redux. It is a pure function (type of
ActionReducer
) - Action: similar as action in Redux. It is object composed of
type
andpayload
(optional)
- Install ngrx/store
- Create Action creator, Action Reducer
- Connect Store to Module
- Connect Store to Component
npm install @ngrx/store @ngrx/effects @ngrx/router-store --save
- Implement
Action
interface - If action has data, override constructor with
payload
parameter
export const LOAD = '[WidgetManagement] Load';
export const LOAD_SUCCESS = '[WidgetManagement] Load Success';
/**
* Load Collection Actions
*/
export class Load implements Action {
readonly type = LOAD;
}
export class LoadSuccess implements Action {
readonly type = LOAD_SUCCESS;
constructor(public payload: Widget[]) {}
}
- Define a state interface for each feature's reducers and it's initial value (Shape of State)
export interface State {
loading: boolean;
loaded: boolean;
items: Widget[];
}
export const initialState: State = {
loading: false,
loaded: false,
items: []
};
- A function has a state and an action as inputs. State is not mutate directly, returns a new state.
export function reducer(
state = initialState,
action: WidgetManagementActions.Actions
): State {
switch (action.type) {
case WidgetManagementActions.LOAD: {
return Object.assign({}, state, {
loading: true,
});
}
case WidgetManagementActions.LOAD_SUCCESS: {
const widgets = action.payload;
return {
loaded: true,
loading: false,
items: widgets,
};
}
default: {
return state;
}
}
}
NOTE: Unit test reducer?
- Define module's state that combines reducers
- Map module's state as a property of root's state
import * as fromWidgets from './widgets';
import * as fromRoot from '../../reducers';
export interface WidgetsState {
widgets: fromWidgets.State;
}
export interface State extends fromRoot.State {
widgets: WidgetsState;
}
- Reducers for module
export const reducers = {
widgets: fromWidgets.reducer
};
- Connect to root module
@NgModule({
imports: [
// ...
StoreModule.forRoot(reducers),
],
// ...
})
- Connect to feature module
@NgModule({
imports: [
// ...
StoreModule.forFeature('widgets', reducers),
],
// ...
})
- Inject action creator and store through component's constructor
-
Store
imported from'ngrx/store'
-
constructor(private store: Store<fromWidgets.State>) {}
- Get state,
select
function of store returns an observable
this.widgets$ = store.select(fromWidgets.getWidgets);
Store is an BehaviorSubject (ie: it is also a Observable and Observer and when it is subscribed, it emits the last emitted items to the observer).
When a component subscribes to Store, it will receive the current State.
- Use
async
pipe to transform the observable in template
<h4>Total Widgets: {{(widgets$ | async)?.length}}</h4>
- Dispatch an action
import * as widgets from '../actions/widgets';
// ...
this.store.dispatch(new widgets.Load());
https://github.com/Tuong-Nguyen/Angular-D3-Cometd/wiki/ngrx-store-Effects-&-Selectors