NgRx: More Than Just a Store

For many developers, the NgRx team's output is synonymous with a single library for managing global application state. In fact, the term "NgRx" is often used interchangeably with "@ngrx/store" – perhaps you're among this group?

This perception isn't entirely surprising. The store remains the team's most popular and flagship project, and for a long time, it was their only Angular-dedicated offering.

The NgRx team has noticed this pattern and, while rolling out new features, decided to clarify their vision. For those wanting a deeper dive, Mike Ryan's talk at ng-conf 2020, The State of NgRx, comes highly recommended. It's also worth browsing the official docs to see what's changed; the updated navigation alone offers a quick overview — compare the current version with the previous one.

Early in the new documentation, NgRx is described as a framework for building reactive applications in Angular, with global state management being just one component of that vision. It's clear the team takes application reactivity seriously, and this framing is a positive move toward addressing the topic more holistically.

So, what libraries does NgRx currently offer, and what purpose do they serve? The creators have organized them into three primary categories based on their function: State, Data, and View. Let's examine each in turn.

NgRx – not only store — figure 1

State

This is likely the most familiar category. As the name implies, these libraries assist with managing application state. Some entries may be old news, but others might come as a surprise:

  • @ngrx/store – The core of global state management, this RxJS-based library draws inspiration from Redux. It provides a container for state, selectors for reading it, and actions with reducers for modifying it. As the best-known member of the NgRx family, it likely requires no further introduction.
  • @ngrx/store-devtools – Enables state debugging through the Redux DevTools Extension.
  • @ngrx/effects – Facilitates defining behaviors (effects) that respond to data arriving in input streams. The action stream is the most common source; typical outcomes include service calls, data-access operations (like API requests), and other asynchronous tasks. Effects usually return new actions to update state, though this isn't mandatory.
  • @ngrx/router-store – Acts as a link between @ngrx/store and the Angular Router. With this library, routing events become actions, and navigation state is persisted by a reducer in the store, making it easy to access later.
  • @ngrx/entity – Provides support for managing entity collections stored in the store. It helps create reducers and selectors, and perform operations on both entire collections and individual elements.
  • @ngrx/schematics – Contains schematics for generating store-related components and the components that consume them.
  • @ngrx/component-store – The final and most intriguing entry in the State category, as it represents the newest concept here. It debuted in version 10. Previously, NgRx's state solutions focused exclusively on global application state. This library expands that approach by offering tools for managing local state within individual components or component trees. It's worth noting that, by design, it's entirely independent of @ngrx/store.

Data

The first new category currently consists of just one library:

  • @ngrx/data – Initially an independent venture by Ward Bell and John Papa, it was first hosted here. It joined the NgRx fold with version 8. The primary objective is cutting down the boilerplate involved in creating state elements, a pain point that grows with larger, multi-entity applications.

The library offers easily configurable services for managing data and executing CRUD operations, all while leveraging @ngrx/store and other State libraries under the hood. In typical scenarios, it's designed to require just a few lines of code for a given entity's service, and it remains fairly extensible.

View

The newest category, like the previous one, contains a single library — though this one has been part of NgRx from day one:

  • @ngrx/component – This library embodies NgRx's commitment to promoting reactivity beyond state management, targeting components and their views. It currently ships the *ngrxLet directive and the ngrxPush pipe, both designed to solve frequent issues in reactive views that rely on *ngIf or the async pipe. A notable feature is their functionality in applications that don't use zone.js. However, the project's future is somewhat uncertain. A more detailed article dedicated to this library, including its current status, is forthcoming on our blog.

Summary

Whether from Mike Ryan's presentations, the NgRx documentation, or our brief overview, it's hard to miss the team's push to broaden their toolkit and shed the label of being solely about global state management. Several libraries are venturing into new territory—local component state and reactive views, for example. While the @ngrx/component situation suggests some caution might be warranted, expanding NgRx's library set is still a welcome development that should benefit the entire community.

Have you already adopted any of the newer NgRx offerings in your projects? We'd love to hear about your experiences in the comments!