In This Article

This post kicks off a series focused on crafting reactive Angular applications with NgRx for state management. I'll begin by sharing how I came to appreciate NgRx and introduce a sample project that will serve as our foundation throughout. To get the full value from this series, you should have a working knowledge of core NgRx concepts. In the posts that follow, I'll reflect on both the strengths and pitfalls I've encountered with state management and highlight recommended practices for NgRx.

If you'd rather watch than read, there's a video companion available:

You can grab the source code from

GitHub logo rainerhahnekamp / ngrx-best-practices

The long road to a state solution

I've been building JavaScript-heavy applications since the year 2000. Back then, we called it DHTML, and our toolkit was primarily Visual InterDev. There were no JavaScript frameworks to speak of. I was always eager to explore the emerging technologies of the era: Dojo, ExtJs, AngularJS.

Even then, I sensed a fundamental issue with how I handled data—especially when that data was shared across multiple parts of the interface. If one section changed, how could I keep everything else in sync?

My solutions were crude: I wrote notification functions, refreshed entire pages after updates, and employed other methods I'd rather not revisit.

So, when I first heard about the Flux architecture, I was immediately intrigued. It promised a direct answer to this long-standing problem, wrapped in a catchy phrase: state management.

That was several years ago. I can honestly say my enthusiasm hasn't faded.

The case for state management

A common question is whether state management adds unnecessary complexity. My stance is clear: no. The moment you have multiple components depending on the same state, state management becomes valuable. While some projects might not require it, I believe those are the exception. In my experience, the need arises sooner than you'd expect.

For implementation, I'm a proponent of NgRx. It brings a clear structure to my code. Each piece has a defined role, which makes navigating the codebase easier—not just for me, but for anyone new to the team. As long as they're familiar with NgRx, they can hit the ground running. Plus, it helps me avoid repeating past mistakes. NgRx embodies best practices, so I can trust its built-in patterns.

However, endorsing NgRx broadly doesn't mean we should use it everywhere. If a state is only relevant to a single component, stick with simpler options. There are some exceptions to this rule, which I'll cover in a later article.

What's the trade-off? State management introduces a fair amount of boilerplate. That shouldn't be a deterrent. As your project expands, the advantages will quickly outweigh the initial overhead.

NgRx's disciplined approach can sometimes feel a bit rigid or verbose. But those challenges are manageable. By following established best practices—some of which we'll explore in this series—we can smooth over those rough edges. That's likely why you're here, right?

Meet Eternal: a practical example

To keep things straightforward, our example is a basic CRUD application centered on a customer entity. It displays a list of customers and includes a form for creating or editing entries. The data model, Customer, is defined by the following interface.

In NgRx terms, we'll define actions for loading, updating, adding, and deleting. Because these operations involve a backend, they follow the expected pattern of paired actions, such as "load" and "loaded". Effects will manage the backend interactions, and we'll also set up selectors.

The UI itself is minimal. One component handles the customer list, while a detail component manages the add/edit form. The detail view also includes a button to delete an entry.

A note before diving in

Even with a good grasp of state management, you'll likely encounter scenarios where the official NgRx documentation doesn't provide clear guidance. My hope is that the best practices collected in this series will offer some direction in those tricky situations.

If you're already well-versed in NgRx, I still think you might find a useful tip or two here. And if you're a veteran who finds nothing new, I'd welcome your feedback—or perhaps a best practice you think is missing from my list.