Skip to content

Instantly share code, notes, and snippets.

@GregOnNet
Last active March 23, 2020 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GregOnNet/8e2eac5ada22c6e15e23d3d4bd01487c to your computer and use it in GitHub Desktop.
Save GregOnNet/8e2eac5ada22c6e15e23d3d4bd01487c to your computer and use it in GitHub Desktop.
he-ngrx-article-snippets
EffectsModule.forRoot([])
import { createAction, props } from '@ngrx/store';
export const increment = createAction(
'[Counter] Increment',
props<{ payload: number }>()
);
export const decrement = createAction(
'[Counter] Decrement',
props<{ payload: number }>()
);
constructor(private store: Store) {
// Vorher
this.count = this.store.pipe(
select((state: any) => state.counter.count)
);
// Nachher
this.count = this.store.pipe(select(count));
}
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs';
import { decrement, increment } from './store/counter.actions';
@Component({
selector: 'app-counter',
template: `
<strong>{{ count | async }}</strong>
<button (click)="increment(1)">Increment</button>
<button (click)="decrement(1)">Decrement</button>
`
})
export class CounterComponent {
count: Observable<number>;
constructor(private store: Store) {
this.count = this.store.pipe(
select((state: any) => state.counter.count)
);
}
increment(payload: number) {
this.store.dispatch(increment({ payload }));
}
decrement(payload: number) {
this.store.dispatch(decrement({ payload }));
}
}
@Injectable()
export class CounterEffects {
randomAdd = createEffect(() =>
this.actions.pipe(
ofType(randomAdd),
concatMap(() =>
randomizedNumber().pipe(
map(value => add({ payload: { value } })),
catchError(message => of(logInfo(message)))
)
)
)
);
constructor(private actions: Actions) {}
}
EffectsModule.forFeature([CounterEffects])
import { StoreModule } from '@ngrx/store';
import * as fromCounter from './store/counter.reducer';
// … @NgModule Definition
StoreModule.forFeature(
fromCounter.counterFeatureKey,
fromCounter.reducer
)
import { createReducer, on } from '@ngrx/store';
import { increment, decrement } from './counter.actions';
export const initialState: State = {
count: 0
};
export const reducer = createReducer(
initialState,
on(increment, (state, { payload }) => ({
...state,
count: state.count + payload
})),
on(decrement, (state, { payload }) => ({
...state,
count: state.count - payload
}))
);
import { createFeatureSelector, createSelector } from '@ngrx/store';
import * as fromCounter from './counter.reducer';
export const counterState = createFeatureSelector<fromCounter.State> (
fromCounter.counterFeatureKey
);
export const count = createSelector(
counterState,
state => state.count
);
this.store.subscribe(state => {
console.log('Counter', state.counter.count);
console.log('Log Messages', state.log.infos);
});
randomAdd = createEffect(() =>
this.actions.pipe(...),
{ dispatch: false }
);
import { createEntityAdapter, ... } from '@ngrx/store';
export const adapter = createEntityAdapter<Message>();
export const loggerReducer = createReducer(
adapter.getInitialState(),
on(logInfo, (state, { payload }) => adapter.addOne(payload, state))
);
import { adapter } from './logger.reducer';
export const loggerFeatureKey = 'logger';
const featureLogger = createFeatureSelector<LoggerState>(loggerFeatureKey);
export const {
selectAll,
selectTotal,
selectEntities,
selectIds
} = adapter.getSelectors(featureLogger);
counter/
┣ store/
┃ ┣ counter.actions.spec.ts
┃ ┣ counter.actions.ts
┃ ┣ counter.effects.spec.ts
┃ ┣ counter.effects.ts
┃ ┣ counter.reducer.spec.ts
┃ ┣ counter.reducer.ts
┃ ┣ counter.selectors.spec.ts
┃ ┗ counter.selectors.ts
┣ counter.component.ts
┗ counter.module.ts
const initialState: State = { count: 0 };
function counterReducer(
state = initialState,
action: Action
): State {
// switch-case action.type ...
}
function counterReducer(state: State, action: Action): State {
switch (action.type) {
case '[Counter] Add':
return {
...state,
count: state.count + action.payload
};
default: return state;
}
}
StoreModule.forRoot({
counter: counterReducer,
log: logReducer
})
!environment.production
? StoreDevtoolsModule.instrument()
: []
const action = {
type: '[Counter] Add',
payload: 3
}
@Component({/*... */})
export class ListComponent {
constructor(
private route: ActivatedRoute,
private userService: UserService,
private shoppingService: ShoppingService,
private invoiceService: InvoiceService,
) {}
}
StoreModule.forRoot(reducers, {
metaReducers,
runtimeChecks: {
strictStateImmutability: true,
strictActionImmutability: true,
}
})
import { EntityState } from '@ngrx/entity';
export interface Message {
id: string;
text: string;
}
export interface LoggerState extends EntityState<Message> {}
{
counter: {
count: 0
},
log: {
infos: []
}
}
{
featureA: { ... },
featureB: { ... }
}
storeActions.pipe(
filter(action => action.type === 'Initiate'),
switchMap(action => apiCall.execute(action.payload)),
map(result => store.dispatch({
type: 'Success', payload: result
})),
catchError(err => store.dispatch({
type: 'ERROR', payload: err.message
}))
)
@Component({ /* ... */ })
export class CounterComponent {
constructor(private store: Store<State>) {}
add(count: number) {
this.store.dispatch({
type: '[Counter] Add',
payload: count
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment