on
Simple RxJS-based State Management in Angular
I got a new project to work on and needed a state management library for that project. Because my team lead didn’t have experience with modern state management libraries and the project appears to be small (even in perspective), I wanted a simple solution. A solution, which would be easy to use and would work nicely with Angular. Google led me to this article and I decided to use it in the new project.
Warning! This blog post is not a tutorial and is my experience only. If you’re looking for a guide, please, refer to “Simple state management in Angular with only Services and RxJS” article at dev.to.
Let’s review the approach first. The idea is pretty simple. You have a state (plain js object) wrapped in BehaviorSubject. Any ng component can be subscribed to the BehaviorSubject in order to get updates of the app’s state. To achieve that, we need to convert the BehaviorSubject to Observable and apply rxjs operators to get slices of the state:
Inside an ng component:
The AsyncPipe is quite important here. In addition to that, the OnPush change detection strategy could be used to improve performance but in my case, when the application is not big or medium size, this is not important. And that’s pretty much all:
- We set the initial state in BehaviorSubject’s constructor
- Nobody outside the Store should have access to the BehaviorSubject because it has the write rights
- Writing to state should be handled by specialized Store methods (ex: addTodo, removeTodo, etc)
- Create one BehaviorSubject per store entity, for example if you have TodoGroups create a new BehaviorSubject for it, as well as the observable$, and getters/setters
The solution is, indeed, pretty simple and doesn’t require additional libraries in Angular. But it has a few drawbacks (or lack of useful features) such as:
- There’s no history of the state. The history might be helpful in some cases (not only the undo/redo but the others as well).
- There’s no middleware. For example, I don’t see how a logger service could be added (as independent entity).
- The solution is not quite flexible.
On the bright side, this solution is simple and efficient. It might be perfect for small apps. For better performance, use the OnPush change detection strategy together with async pipes and distinctUntilChanged rxjs operator.