I was almost about to name this header Angular 2 Redux Sagas NGRX and State Management. There is so much happening in the world of state management but keeping things simple is key.
What is a state?
What is state management? There are several type of states. Typical a local ui state which frankly no-one cares about. Those are property related in your UI. A ui-state. The second one is your application state. So several parts of your application are in a certain state. Your model has changed and you have to manage IO states. Those changes are not local. The coordination of states is challenging within Angular 1.
Consistency is the magic word. If on part of you app is being updated but the other part isn’t. In most cases parts of your app are depending on calculations to be done before anything can be updated in specific area. This makes your apps, or modules depended on other models in your app. That is okay as long as you don’t grow because it could potentially create a very confusing user experience.
Imagine you have list of processes running. Those processes are part of an upload. Now imagine that each process will show a responsive upload and those will vanish after completion. So, you stay on the same page but a simple counter hasn’t been updated and that counter is supposed to tell you the amount of uploads that have successfully finished. If that counter stays at 0 you either become frustrated or do it all over again. The coordination of those states is not simple.
What happens right now is to make state management easier. Ideas like Redux. The core ideas are, store your state in one place and mutate the state of your app when you need the data. Second, your state is derived from another state but your UI will only be updated if a routine has finished its work. This way your application logic and your view logic are separated and your components are stand alone.
So what made Redux stand out
The reason we use flux is that we never had a framework that helped us to do all the magic we expect from a new website, such as optimistic updates, asynchronous services. Most of older frameworks had to apply a very complicated logic to get this working that it was almost not useful to actually go through with the changes? Redux is very straight forward and reproducible. So if something goes wrong you copy the last states and trace all those logs to find your incorrect behaviour. If you see some specific state that is wrong, you instantly understand and locate apps problems. Because only one function is supposed to be responsible for this particular area.
The core concepts of Redux are, actions are serialisable and they are plain objects. You need to be able to serialise your services and logs in order to trace back your bugs. So if you store those logs in localStorage, you will be able to trace back your states and replay them.
So how does Angular 2 work with Redux? You can use it even with Angular 1 but if you have to be careful with two way bindings. You want to flush out your current state and replace it with a new one. To keep your constrains straight. With Angular 2 you have more constrains. Unidirectional data flow is one of them. It even makes Angular a lot more performant. Things like render sideways are totally new keywords to me but they seem to be beneficial to Angular 2 and its component tree.
Predictability and record sessions is a pro for Redux. You can use the same stores to prefetch data for your server rendered components. It makes rendering on the server easier. The downside, “What are the disadvantages of storing all your state in a single immutable atom?”. Some of the points in this issue, It is not initially obvious how to create apps with sub apps (redux has one store with a single state tree) so it is not easy to disconnect stores and models. So it’s a bit complicated for enterprise apps. In React all this is disconnected due to the usage of components. Another issue, if you have a giant list of data, having React checks like shouldComponentUpdate is great, but even those checks become expensive with lots of data in Redux. So if you have a high rate of updates per second, don’t use Redux. Don’t go for the hype in the ecosystem.
In terms of cashing, Redux doesn’t have opinions on how to do it. In most apps you might not need to cash but in case you want to do it, implement some kind of garbage collection. It is just not meant to be for Redux.
Reactive patterns in Angular 2
In the Angular ecosystem, there are different pattern and one of which is a reactive pattern.
There are still applications states in a giant immutable data structure, submit actions to process new states, and there is a state function that returns an observable state. So basically this is like Redux. But there are differences. One is the state function is invoked only once. Second, observables are push able that means they async and sync able. Third, you can wait for functions to arrive and throw errors or result functions in a very easy way. This is very declarative way for asynchronous processes to work with.
It gives you a lot of freedom. But you loose the synchronous guarantees. You might loose updates and don’t even know it. Redux is better readable and comprehensible in that case. If you use observables for async it will be hard to track if you don’t manage the correct load order. Having said that, async functionality isn’t deterministic is hard anyway.
A project called Redux Saga
There is a project called Redux saga. You use ES6 generator functions to control your asynchronous flow. For every action I am going to make specific requests. Instead of dispatching Thunks which get handled by the redux-thunk middleware, you create Sagas to gather all your Side Effects logic in a central place.
The fact that Sagas yield plain Objects makes it easy to test all the logic inside your Generator by simply iterating over the yielded Objects and doing simple equality tests. Furthermore, tasks started in redux-saga can be cancelled at any moment either manually or automatically by putting them in a race with other Effects.
About the implementation, it works but I think the sagas should rather be able to be autonomous. I don’t like the idea to use getState within saga. The sagas receive all the events so they don’t need to pick state from the UI redux state. Instead you can easily use the event log to make the saga decoupled from your Redux state.
Immutable Angular 2 and Benefits
Angular 2 can use immutable data to bypass large areas of the component tree in case you don’t need to update them but you can also make use of observables. You have components that bind to observables and change when necessary. For Angular 2 you can use NGRX. Some of Redux API choices seems to be derived from NGRX which means you can use both and have proper methods to interact with.
When you try to implement those libraries you will need to understand their underlying methodologies. But working with those libraries will probably make you smarter in the sense to make better and informed choices.
Try to get rid of dependencies for models and try to build more than one store. A separate this will help with app performance and isolation of domains.
There are advantages of synchronous and tradeoffs too. Specifically when your production goes async, you loose lots of your tool chain. Testing is a big part of it. The pain continues
Here is an app based on NGRX: https://github.com/simpulton/ngrx-rest-app