Understanding State Management — Angular

Byteridge
Byteridge
Published in
6 min readSep 10, 2020

The aim of this post is not to discard the usefulness of data store libraries, it’s about auditing whether built-in Angular tools can solve problems that external stores tend to solve, about their comparison. It’s also about discouragement of adopting stuff prior to realizing the actual utilization and need, and not following the hype blindly.

In this post we are going to understand:

  • What is state
  • What is a state in a web application
  • Categories of state
  • different ways to manage state
  • Libraries to manage angular application state

So, Unlike classic web applications, single-page applications have an application state — and this must be managed to avoid inconsistencies and data binding cycles. That’s why developers of single-page applications have to deal with state management.

What is the application state?

Have a look at the image below, how many items in this image can be considered as a state?

The answer is everything you see in this image that can be considered as a state of a web application. from our web page’s button color to our web services response data, everything can be considered as a state of our application and you might want to take care of these states.

Categories of states in a web application:

  1. Server state — Data resides at server or database which belongs to the client application is called as server state
  2. Persistent state — When a client makes a call to the server and the server responds with some state(data) that is called persistent state
  3. URL/Router state — Any information resides in URL is called as URL/Router state
  4. Client State — current client application state, after all, manipulations from URL state, for e.g applying some filter based on an URL parameter
  5. Transient State — current client application state, after all, manipulations that are not represented by URL parameters
  6. Local UI state — State of UI components like button color

State Synchronization

In the real time applications, you might come across to scenario where you will have web service fetching some list of items and you are providing a filter option to filter those items based on some condition at the client side.

So in this example, two states mentioned in the blue border are really important to be taken care, because they are in two different domains so they should always be synchronized. The other two states, “Client manipulation” and “UI component” states are also important but they are really easy to manage so we will not discuss these states.

How to manage state in a web application:

Now we need someplace to store our application data at a place from where all components can access that data, to achieve this here are some suggestions:

Some old school Suggestions:

  • Save everything in the URL
  • Save everything in the cookies
  • Sessions and local storage
  • Hidden fields
  • Keep it stateless, don’t care about the state

Yes, the above-mentioned suggestions are correct and can be used to implement state management, but some problems will come along if we use these methods, for example — most of the data in the URL are in plain text and there is a limitation of size, etc. that is why these methods should not be considered to manage state.

better suggestions:

  • Smart and dumb components
  • Observable data services
  • State manage libraries

Smart and dumb components:

In this concept, while designing the web application we can categorize our components into smart and dumb components where the smart component has business logics and knows about application states, and also knows how to manage states.
on the other hand, dumb components will not have any business logic and will not have any idea about states.

Example:

If you design your application using this concept you will have your component structure like this

Here bookList and bookItem components contain business logic and are stateful hence they are smart components and “like-Button” and “shopping cart” are dumb ones.

To implement something like this we have to use @Inputs and @Output decorators as shown below:

And done! but wait… with only three components the code looks so ugly and unmanageable, imagine if you have a very complex application.

Limitation:

  • Just parent-child interaction between components
  • Not ideal for complex applications
  • Unreadable code

Observable data services:

In this concept, we will have one separate service which will be responsible to manage data and state of components.
This implementation will require rxjs library’s observables and subjects.

Now you can inject this service to your components and emit values to this subject and all the components which are subscribed to this subject will get the value and gets their state updated.
also, we can subscribe to the router’s params change to manage the router state.
that’s it, all done…so this means rxjs is providing us everything that we need to manage our application state right?

After implementing the above steps your application structure will look like this:

but wait.. there is a scenario :(
What if you have multiple shared services? then your application structure will look like this:

Now that becomes really complicated to manage.. right?
Now if you have an application structure like this then you probably will seek some other better alternative to achieve state management.
And that is where external state management libraries come into the picture.

NgRx — a popular state management solution for angular ecosystem based on redux

when to consider this library in your angular application for state management:

  • Shared — if you have states shared over multiple shared services in your application
  • Hydrated — if your state keeps hydrated from any of the sources like local storage
  • Available — in your state is so available like you have your state in routes
  • Retrieved — if your state is retrieved with side effects like API data calls
  • Impacted — if your state is impacted by other states

Now NgRx is based on a few principles of Redux mentioned below:

  • Single source of truth — One objectory that can be serializable and it can also be hydrated
  • Read only — State can only be manipulated only via reducers
  • Pure function — All the reducers we will use to manipulate state will be pure functions

Now let’s see this implementation in a picture:

So as mentioned in the picture, we have our state from where we can query part of the state and show it to our component.
Now if we want to change something in the state we will dispatch an action.
Actions will be received by reducers which are nothing but pure functions to produce a new state and send it back to the original state.

Benefits of having state management over traditional application without state management

  • Allow us to minimize the number of http requests done to the server
  • Allow us to easily have parts of view reflect new versions of data
  • Allow us to have much improved user experience with minimal loading indicators

Long journey so far… so in my next post i am going to explain how to actually implement selectors, actions and reducers in an angular application using NgRx.

Written By — Hitesh Garg, Software Development Engineer

--

--