Hi everyone !
I often found myself creating custom solutions to state management problems for my junior coworkers, because lets get real about this…. reactive programming and ngrx/store are pretty difficult to understand and more to master.
I LOVE Rxjs !
Customizing flows of data trough observables and combining their results are one of my guilty pleasures in development, but not everyone feels the same when having to share information between brother components or different modules. You may often use services, input and outputs, or even create Rxjs’s observables to try to fix this, but as the application grows ngrx/store becomes a sweet choice… if you and your teammates have the sufficient experience for the challenge.
So… what happens if you are like me with an application that needs the sharing of information, and that could benefit of ngrx/store, but you or your teammates doesn't have enough experience to use it ?
Reactive programming is the concept of developing code where different entities are watching trough an information channel for data to pass, and when it does, each entity will “react” to that situation doing their business logic.
Imagine an empty tube with 3 holes in it, at each hole we have a person looking trough it and waiting for a little ball to pass. Because each person is different, they will see different aspects of the ball. For example, one can see that the ball is red, another that the ball is bouncing a little when it’s passing trough …or even that maybe it’s not a ball at all !.
That’s exactly what reactive programming is ! we have an information channel (observables) containing the data that is passing trough it, and on the other hand we have entities (the angular components for example) that will be subscribed and waiting for that information to pass …and when it does, they will react to it doing what ever business logic we coded for them.
Redux, Ngrx/store, etc. are libraries that provide tools to manage the state of the application using the concept of “A Single Source Of Truth”, these means that the whole information of the app will be contained inside a “store”, a place where you can access useful and up to date information.
Each time a change happens inside your application, information wise, the store will be updated with the latest changes. So you don’t need to call the back end again for an update if not needed and also all entities that are watching the store’s states will be automatically alerted of the change.
Rxjs is a library containing a lot of amazing tools to manage these information channels, these provide the ability to create, combine and modify observables with the inclusion of new kinds to use, each one with their own functionalities.
We are going to use Behaviour Subjects a lot in this case, it’s an observable that will always contain the last data that passed trough it….which is amazing for what we want to do ! When ever we send information trough the Behaviour Subject, even if an entity subscribes AFTER the information has been sent, it will receive the latest data ! so we don’t loose anything.
The main concept of Gentleman State Manager, is providing an useful way to manage the state of your application, using understandable and cristal clear tools like Rxjs to do so. In short, we create an array of observables identified by their key, that can be increased in size by each module (so yes, we use lazy loading !) to manage the information that passes trough the different entities of your Angular application. You only have to create the initial object at the app module, and then if you have a lazy loaded module, you can increase the array by adding more items !.
But don’t worry, the main idea of the library is to be easy to use and more than everything…transparent, you can access the array data at any place to get or send the information stored inside with a super easy and useful API that is detailed next.
1- Create an object using the SourceOfTruthInitiate class provided by the library. I recommend having a state.ts per module, representing the state interfaces and properties :
state.ts for Root ( AppModule ):
export interface FirstState {
stateProperty: string | null;
}
export enum FirstStateProperties {
STATEPROPERTY: 'stateProperty'
}
export enum StoreKeys {
FIRSTSTATE: 'firstState'
}
AppModule:
const sourceOfTruthInitiate: SourceOfTruthInitiate[] = [
{
key: StoreKeys.FIRSTSTATE,
state: {
stateProperty: 'your state property value'
},
stateProperties: FirstStateProperties
}
];