NgRx
01 / 02

Store, Actions, Reducers & Selectors

Store, Actions, Reducers & Selectors

Redux for Angular, Built on RxJS

NgRx brings Redux's unidirectional data flow to Angular: one centralized, immutable state tree (the Store) that the whole app reads from, updated only through dispatched actions — built on RxJS observables, which Angular already relies on.

Actions & Pure Reducers

export const increment = createAction('[Counter] Increment')
export const reset = createAction('[Counter] Reset')

export const counterReducer = createReducer(
  0,
  on(increment, (state) => state + 1),
  on(reset, () => 0)
)

Actions describe an event ("increment happened") — they don't mutate anything themselves. Reducers must be pure functions that return a new state rather than mutate the existing one, because OnPush change detection and memoized selectors compare object references, not deep contents.

Memoized Selectors

export const selectItems = (state: AppState) => state.items.entities
export const selectCompletedItems = createSelector(
  selectItems,
  (items) => items.filter((i) => i.completed)
)

Selectors decouple components from the store's shape. createSelector memoizes the result, so expensive derivations only recompute when their specific input selectors' outputs actually change by reference — not on every unrelated state change.

Consuming State in Templates

<ul>
  <li *ngFor="let item of completedItems$ | async">{{ item.name }}</li>
</ul>

The async pipe subscribes automatically, renders emitted values, and unsubscribes on component destroy — avoiding the common bug of a manual subscription left dangling as a memory leak.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free