DATEV Nine-Nine | The Sweetness of the NgRx Component Store
By: Matthias Alt, Stephan Bierwirth & Gerrit Riesch
Intro
State management can be one of the trickiest parts of frontend development. There are tons of different solutions in varying degrees of complexity and the implementations can become hard to understand very quickly. To our surprise there is a solution for small and/or component-scoped states, which is as sweet as the inventory of a candy store: NgRx Component Store. This beauty has been around for two years now but somehow, we never got a chance to try it out… Until now.
Motivation
In a recent greenfield project, we had to decide what kind of state management to use for a complex stepper view component. We all know how much pain it can be to introduce a state management system at a late project stage or to switch to a different solution. Of course this can happen and there are ways, such as facades, to make a switch easier. Nevertheless, we wanted to pick the right tool for the job. In our case we were aiming for a lightweight state management that’s easy to understand and to extend.
The right tool
So how to decide whether to use the NgRx Component Store or the good ole’ NgRx Store? First of all, it doesn’t have to be an or and might as well be an and decision because the two solutions can be combined. But for now, let’s start with the Component Store and when it should be considered. An indicator for using the component store can be that the app is small, the component tree is not very deep and not interconnected and that there is a clear separation of state ownership at different nodes in the component tree. Another thing to consider is if the state is only needed on some pages of the application and can be cleaned up after navigation. Not all of these factors are a must and there are some other factors but in general one can say that the Component Store is responsible for small(ish), encapsulated and more local state and works also great for UI state.
Implementation
In this guide we want to show you with a simple example how to use the component store. To demonstrate the basic concepts of the component store, we will create a small app with a dashboard component which will display a list of all officers in duty and the count of their solved cases. In Order to follow the example, all you need is a bare angular app. It’s really easy so we have only provided some snippets. To get started we have to (surprise!) install the package. ;)
npm install @ngrx/component-store — save
In the next step we have to create a precinct.state.ts file to describe your state model and to provide a default state (which is optional):
Next up we are getting to the core, the precinct.store.ts file where the magic happens. If you provide the store in root, you will have a singleton across your app. If you do not want that you have to provide it in the module of your choice.
We extend the default component store and provide our state model and we set the default state in the constructor. Then we have selectors for the state, effects and reducers. NgRx provides us with lots of helper functions (like patchState, tapResponse etc.) and therefore we can keep the store nimble and clean.
In this example we added a state selector for the officers on duty, an effect for triggering side effects whenever those officers change and a method to add an officer to the list and to set the count of the solved cases. Of course, you can do a lot more, but this includes the essence and is all that’s needed to get started.
In typical DATEV-Nine-Nine fashion we want to provide you with a way to test your code. Actually it’s really easy as well and in our precinct.store.spec.ts we demonstrate testing a selector and a reducer.
Finally we have to display our data in our officers-dashboard.component.ts. You can access the officersOnDuty$ there by injecting the store and e.g., using the async pipe in the template (not shown here). Updating works by simply calling the store methods here.
Alternatives
So, what about the NgRx Store and other non-NgRx Solutions? Of course, we had the default NgRx store in consideration. It has lots of pros like being the de facto standard and most widely known so that developers new to the project will be more likely to have an easier time getting on board. Also, it’s probably the most scalable solution. But it’s complex and has just too much overhead for our small state management needs. We also did look at the more minimalistic store solutions like Elf (next to Akita) and NGXS. These are really cool libraries, but we wanted to keep the door open to maybe introduce the “big” NgRx store at some point and also, we wanted to use NgRx because we know its syntax and style. So, because of that we concluded that the NgRx Component Store was the perfect fit for our project. We did not regret this choice. Finally, there is of course always the option to just use a plain angular service for your state management needs. We did think about this solution as well but discarded it for the NgRx Component Store because the Component Store has barely any more overhead than the service and gives you structure and functions that will make it easier to maintain in the long run. All these considerations are just what we arrived at for our project, and we want to emphasize that none of the above solutions is superior. It’s just a case of the right tool for the right job as usual.
Final thoughts
In this article we showed you what the NgRx Component Store is, why we really love it and how easy it is in usage and testing. Of course, it’s no silver bullet and you have to decide if it’s the right fit for any given application. Nevertheless, we encourage you to try it out! It’s REALLY cool.
We hope you enjoyed our blog, and we would love to see you next time!
Your three DATEV Nine-Nine detectives,