All topics
Stateadvanced

NgRx Actions and Reducers

Go deeper into action design conventions and reducer composition patterns in a real NgRx application.

Beyond the basic mechanics, real NgRx applications follow specific conventions for actions and reducers that interviewers use to distinguish candidates who've genuinely worked with NgRx from those who've only read the introductory docs. The most important convention is action naming: NgRx's community style guide recommends the [Source] Event format ('[Product List] Load Products', '[Product API] Load Products Success'), which groups actions by where they originated and makes a Redux DevTools action log genuinely readable when debugging a real application with hundreds of possible actions.

It's like a large newsroom where every reporter (feature) files stories under a clear, source-labeled byline ([Source] Event), and the async trio pattern is like always filing 'story submitted,' 'story published,' and 'story rejected' as three distinct, unambiguous updates rather than one vague status update that could mean any of the three.

Key Concepts

1
A very common, easy-to-miss pattern is representing an async operation as a trio of actions rather than one: a triggering action (loadProducts), a success action (loadProductsSuccess, carrying the fetched data as its payload), and a failure action (loadProductsFailure, carrying the error) — this trio pattern lets the reducer handle three distinct, explicit state transitions (loading, success, error) rather than trying to cram ambiguous state into a single action's shape.
loadProductsloadProductsSuccessloadProductsFailure
2
createReducer's on() function pattern-matches a specific action creator (or several, comma-separated, sharing the same handler) to a handler function, and because a single slice of state might need to react to actions dispatched from many different features, it's entirely normal and expected for one reducer to have on() handlers for actions defined and dispatched from a totally different feature's action file.
createReduceron()
3
A deeper interview question asks about reducer composition for large state trees: NgRx typically combines many small, feature-scoped reducers (each managing its own slice of the overall state tree) via combineReducers internally (handled by StoreModule.forFeature/provideState under the hood), so no single reducer function needs to know about or handle the entire application's state — each stays focused on its own slice, mirroring the same single-responsibility principle that motivates Service Composition Patterns elsewhere in Angular.
combineReducersStoreModule.forFeatureprovideState