1. Original Angular component with @Input and @Output
Let’s say you have a Counter Component:
// counter.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<div>
<button (click)="decrement()">-</button>
<span>{{ count }}</span>
<button (click)="increment()">+</button>
</div>
`,
})
export class CounterComponent {
@Input() count = 0;
@Output() countChange = new EventEmitter<number>();
increment() {
this.countChange.emit(this.count + 1);
}
decrement() {
this.countChange.emit(this.count - 1);
}
}
2. Now let’s convert it to use NgRx for state
First, assume you already have an NgRx store set up.
We’ll need:
Actions
Reducer
Selectors
Dispatch and Select in the component
Step 1: Create Actions
// counter.actions.ts
import { createAction } from '@ngrx/store';
export const increment = createAction('[Counter] Increment');
export const decrement = createAction('[Counter] Decrement');
Step 2: Create Reducer
// counter.reducer.ts
import { createReducer, on } from '@ngrx/store';
import * as CounterActions from './counter.actions';
export interface CounterState {
count: number;
}
export const initialState: CounterState = {
count: 0,
};
export const counterReducer = createReducer(
initialState,
on(CounterActions.increment, (state) => ({ ...state, count: state.count + 1 })),
on(CounterActions.decrement, (state) => ({ ...state, count: state.count - 1 }))
);
Step 3: Create Selectors
// counter.selectors.ts
import { createSelector, createFeatureSelector } from '@ngrx/store';
import { CounterState } from './counter.reducer';
export const selectCounterState = createFeatureSelector<CounterState>('counter');
export const selectCount = createSelector(
selectCounterState,
(state) => state.count
);
Step 4: Update the Component
// counter.component.ts
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import * as CounterActions from './counter.actions';
import { selectCount } from './counter.selectors';
@Component({
selector: 'app-counter',
template: `
<div>
<button (click)="decrement()">-</button>
<span>{{ count$ | async }}</span>
<button (click)="increment()">+</button>
</div>
`,
})
export class CounterComponent {
count$: Observable<number>;
constructor(private store: Store) {
this.count$ = this.store.select(selectCount);
}
increment() {
this.store.dispatch(CounterActions.increment());
}
decrement() {
this.store.dispatch(CounterActions.decrement());
}
}
Top comments (0)