Admittedly for most developers state management is one of the toughest parts of growing an application safely while staying maintainable over time.
Angular1 doesn’t promote a specific way to take care of this except for adding it inside services (instead of scopes/components) but the change detection system makes options like immutability or observables useless.
Angular2 corrects this and allows us many more possibilities. We can now use the full power of libraries like Flux/Redux, Immutable.js, RxJS,..
All of this is really vast and exciting!
➜ Starting point
I will start a job in a few months and will be in charge of a new big webapp.
There will be a lot of data to take care of and interact with.
Angular is the de facto choice because of its historical front framework company position and as a full stack solution.
Angular2 will be used and I’m really happy about this but I want to avoid some of the pains that I’ve experienced on previous applications.
➜ Centralize data & unidirectional data flow
Difficulties can appear when data is dispatched in lots of places and managed from everywhere. The result is an application that is hard to update, debug and test.
This is why it is fundamental that application state stays at one place only inside the entire application and follows a unidirectional data flow.
This post reflects my exploration about different current and emerging ways of solving this.
Let's talk about immutability
Working with immutable objects means that you always create a new object when you want to modify it.
You can’t mutate an object. If you want to add an item to an array, you create a new array containing all of the existing items plus the new one. If you want to modify a boolean property on an object, you create a new object with all same properties as the one that you want to change and with the modified boolean.
Immutability leads to better performances for tracking changes: just look at the object references (
objA !== objB), if it didn’t change, there’s nothing to do, no need to check deeper.
➜ How to use it
We can do this with vanilla JS but there is no default type for doing this (contrary to Haskell, Scala,..) so we have to be careful and always keep this in mind.
Otherwise there are libraries made for this, and ↪Immutable.js is the most popular implementation of immutable data structures.
↪ Using immutable data structures in Javacript with Immutable.js
➜ Angular2 and Immutability
Thanks to ↪ChangeDetectionStrategy, we can now tell Angular2 to rerender a component only when its
inputs object changes, so it plays well with immutable objects!
↪ Change detection in Angular2
↪ Immutability and encapsulation in Angular2
↪ Build a minesweeper with Angular2 and Immutable.js: ↪Part1 & ↪part2
↪ Angular2 with Immutable.js
Three main solutions
I’ve identified three main ways to manage data properly: Use a Flux architecture like Redux, do it ‘manually’ with RxJS observables, or use the young Ngrx.
All of these options play well with immutables, Redux makes it a duty and it’s as you want for others.
Solutions 1 : Let Redux take care of it
↪Redux is a tiny (2kb) state container library implementing an unidirectional data flow with predictability as the watchword. It has three main principles:
- The state of the whole application is stored in an object tree (single source of truth).
- Application state is read only (unidirectional data flow).
- State changes are written as pure functions (why it works with immutable data).
➜ Redux history
Facebook was the first to introduce Flux and then a lot of other implementations appeared: Reflux, Flummox, Fluxible, Fluxxor, Fynx, Fluxify,.. and Redux won the battle.
A big advantage for using Redux is its amazing DevTools with features like time travel.
➜ Learn Redux smoothly
Go in this order:
↪ A nice Flux cartoon explanations without code, concepts only.
↪ Another cartoon about Redux and its differences from Flux.
↪ Best explanations about Redux from its author, Dan ABRAMOV, in 30 small live coding videos ★
↪ RDFM: Read the official documentation.
↪ Understand what is a Redux Middleware.
And then you can go deeper about asynchronous actions, using Middlewares like:
➜ Redux with Angular
Redux is historically combined with React to render web application but you can use it to manage your data with any other front-end framework like Angular 1&2, Ember, Aurelia,..
First, you need to understand how this architecture could be implemented with angular, ↪this post shows you how switch a Todo application using Angular1 to using Redux-like state management.
Then read these:
↪ Managing state with Redux and Angular.
↪ Build an Angular2 application with Reflux and Immutable.js
↪ How to use Redux in Angular2 Applications.
You have angular bindings libraries similar to react-redux for React (totally optional):
↪ Ng-redux for Angular 1.X
↪ Ng2-redux for Angular 2.X
Solution 2 : Do it manually with RxJS
If you impose on yourself (and your team) strict rules about state management in your application, you can build well maintainable applications.
Here are few tools and resources to help you achieve this. Immutable data are not mandatory.
➜ A unique facade
Build your own convention to manage your data properly using a single façade following this article:
↪ Anatomy of a large angular application
This facade abstracts the data management part from components. It reduces dependencies and allows more flexibility in developing the system.
Under the hood, you can call multiple services.
➜ Observable streams
Observables are data streams, a very powerful mix between arrays and promises. We can subscribe and unsubscribe to them.
The observer Pattern helps us to keep the unidirectional data flow.
↪ FunFunFunction episode about streams
↪ Introduction to RxJS
➜ RxJS with Angular2
We can use RxJS observables inside Angular2 services. It allows your components to subscribe and be informed when data changes.
Angular2 is really linked to RxJS (which is in version 5 beta 1) and promotes it.
You can use RxJS observables to build stores-like inside a Angular2 application.
↪ Angular2 Observable data services.
↪ Managing state in Angular 2 using RxJs.
↪ Reactive Data Flow in Angular 2
↪ Managing state in Angular2 using RxJS in a Redux-like way ★
Solution 3 : NgRx Everything is an Observable
↪ Ngrx: RxJS powered state management for Angular2 apps, inspired by Redux.
This library goes a step further and makes every state part an observable, then components can subscribe to them.
This approach is really promising and seems to be the next ‘big thing’ in the angular community as the following tweet from @egghead mentions.
Use this library with the included
async pipe and
ChangeDetectionStrategy.OnPush and you will have a massive performance boost in large ng2 applications.
↪ Read more explanations from the author @robwormald.
↪ Build a Better Angular 2 Application with Redux and ngrx. ★
Keep an eye on NG-NL, the next big Angular conference in Amsterdam, there will be many talks about these subjects:
Hope this helps some of you. Tells me your thoughts about it and if I made mistakes.