NgRx + Facades: Better State Management

Thomas Burleson
4 min readAug 11, 2018

--

Prior to Nx 6.2, Nx already provided scalable state management with NgRx.

Now there is a new option when generating NgRx files to also generate a facade on top of your state management… to help you work even better at-scale.

Facades are a programming pattern in which a simpler public interface is provided to mask a composition of internal, more-complex, component usages.

When writing a lot of NgRx code — as many enterprises do — developers quickly accumulate large collections of actions and selectors classes. These classes are used to [respectively] dispatch requests to- and query from- the NgRx Store.

Unfortunately — with this standard approach — each view component is required to know about many NgRx artifacts and about NgRx state management.

Using a Facade — to wrap and blackbox NgRx — simplifies accessing and modifying your NgRx state by masking internal all interactions with the Store, actions, reducers, selectors, and Effects.

While this seems like a rather trivial change (and an extra layer), the Facade has a huge positive impact of developer productivity and yields significantly less complexity in the view layers.

Facades encourage developers to think in two (2) ways:

  • Developers are encouraged to think about explicit public facade API(s).
  • Developers start to think of views as presentational components that simply render data deliver from the Facade observables.

Remember these Facade observables are long-lived streams of data delivered based on queries to specific NgRx state.

Implementing our NgRx Facade

First, let’s take a look at how a Facade is implemented as a injectable service.

The facade has an explicit public API that exposes:

  • public observables (e.g. allCars$ ) to private queries for Store state.
  • public methods (e.g. selectCar() ) that hide internals of Store usages.

View Components + NgRx

Let’s take a look at why the Facade pattern is useful… by comparing a View Component implementation with and without facades.

CarListComponent without Facades:

Component without Facades

The simple CarListComponent definition above ^ is required to import NgRx actions, selectors, and know how to use store.select(), and store.dispatch(). For more real world usages, this quickly gets complicated and messy.

CarListComponent with Facades

Component with Facades

Developers will still leverage NgRx one-way data flows, immutable data structures, store.dispatch(), store.select(), effects for async processing, and more… but all this is hidden from the view layer.

From a view component’s point-of-view, NgRx Facades provide a more explicit public API and less moving parts.

Even better, Facades can inject and use other facades!

With Facades, writing state-dependent view components is much easier. To get hands-on with NgRx facades, check out this StackBlitz demo or use the Nx Schematic ngrx to generate your own NgRx files!

Testing NgRx Facades

Using async/await techniques and mock services, developers can easily test the Facade’s public API.

Nx ngrx schematics will also generate a *.facade.spec.ts class.

Consider the cars.facade.spec.ts shown below:

In the above test class, we are asynchronously testing:

  • allCars$ properties by directly dispatching a `CarsLoaded` action and bypassing any similar functionality in the cars.effects.ts.
  • loadAll() public method using a the standard `LoadCars` action dispatched to the NgRx store.
  • using the Nx utility method readFirst to read a single value from the target observable.
  • using async/await to to ensure our testing and and the resulting output responses match an expected sequence. Note the try/catch used to delegate the error handling todone.fail(err).

Note, if the cars.effects.ts implementation internal used a cars.http.service.ts class, we could — in our test — register a mockup HttpService to simulate the handling a loadCars action.

NgRx Facades with Nx Schematics

Use the latest Nx schematics to create both your NgRx generated files and an associated Facade implementation.:

# See help for the `ngrx` schematic
# Use the '-d' option to test in dryRun mode if desired.
ng g ngrx -h# Generate ngrx files + facade in the 'cars' libraryng g ngrx cars --module=libs/cars/src/lib/cars.module.ts --facade -d

By default the facade classes are not generated with ng g ngrx; use the facade flag to include scaffolding for Facades.

Quick Links:

Special Thanks

I am so grateful for the amazing Angular CLI and the Nx power tools. I am also obligated to say thank you to:

  • Jason Jean for his contributions to this article and for the StackBlitz demo.
  • Joost Zöllner for his original illustration depicting view components coupled to NgrX artifacts.

--

--

Thomas Burleson

Solutions architect expert in NextJS, React and Angular solutions. Formerly a Principal Architect @ Nrwl.io, Team Lead for Angular, Google.