All topics
Stateadvanced

NgRx Store Fundamentals

Explain the core NgRx concepts (store, actions, reducers) and the unidirectional data flow they enforce.

NgRx is Angular's most widely-adopted Redux-pattern state management library, and its core promise is a single, centralized, immutable store of application state, changed only through a strict, predictable, unidirectional data flow — components dispatch actions describing what happened, reducers compute a new state based on that action, and the store notifies subscribers of the updated state, with no component ever mutating shared state directly. Interviewers ask about this because large Angular applications frequently reach for NgRx once state sharing/coordination across many features becomes too complex for scattered services alone, and understanding the core flow is prerequisite to every more advanced NgRx topic.

It's like a court reporter's transcript of a trial — every event (action) is recorded in order, and the official record (state) is only ever updated by appending a new, complete entry based on what was just recorded, never by erasing or editing something that was already written down.

Key Concepts

1
An action is a plain, serializable object describing an event that occurred (typically created via createAction) — importantly, actions describe *what happened*, not *how state should change*, which is a deliberate separation of concerns: the same action could theoretically be handled by multiple reducers or trigger multiple independent side effects, none of which need to know about each other.
actioncreateAction
2
A reducer (typically created via createReducer) is a pure function taking the current state and a dispatched action, returning a *new* state object — never mutating the existing one, which is essential both for NgRx's internal change detection optimizations and for enabling features like time-travel debugging in Redux DevTools, since every past state is preserved as a genuinely distinct, immutable object rather than being overwritten in place.
reducercreateReducer
3
The Store itself is injected like any other Angular service and exposes .dispatch(action) to send actions into the system and .select(selector) (returning an Observable, tying directly into everything covered under Observable Fundamentals and the async pipe) to read specific slices of state reactively — components never read from or write to the store's state directly, only through dispatched actions and selected Observables, which is exactly the discipline that makes large NgRx applications more predictable to reason about than scattered, mutable service-based state.
Store.dispatch(action).select(selector)