Introduction to State Management in Angular v2+
In this article, we will learn about state and state management in Angular v2+. There will be a following article about how to implement state management in Angular v2+ with extensions such as @ngrx/store and @ngrx/effects.
We should begin with explaining the state which might be a mystical term for the beginners. “State” term includes both the state of UI and the state of variables in your code. So any change in your application changes the state.
In Angular or other modern JS frameworks, each component has its own state and a component has no idea about the other components’ states unless we make enable the data flow between components. We use @Input and @Output decorators to pass information between parent and child components in Angular v2+.
It is easy to pass information between components in simple apps. But it gets complicated and painful when you have complex app architecture like the figure below.
Let’s think about how to pass data between Component 2 and Component 6. If you use @Input/@Output it takes 4 hops to get Component 6 from Component 2 and the you should involve the other 3 components in this process.
We should mention about Redux at this point. Redux is an elegant solution architecture which simplifies the state management.
There are three core principles in Redux architecture;
- Single Store: state of the application should be stored in a single “store”. Store is the only responsible in providing data to components. Data flows between component and Store instead of component-to-component.
- Read-only state: state should be read-only or immutable. To change the state, new action should be emitted.
- Pure function reducers: Reducers take the current state and an action and return next state. Reducers should not take any other paramaters outside the function.
Another important point of Redux is that all data in the application flows only one-way, in other words data flow is unidirectional. Data flow in an application can be seen from the figure below.
- Component dispatch an action
- Reducer in the store take the action and produce a new state
- New state pass to the component from Store.
@ngrx/store is a state management extension for Angular applications inspired by Redux. It imports all core concepts from Redux. From now on, we will use @ngrx/store terms instead of Redux.
Store is the core structure where actions, reducers and state are located. Store receives actions as inputs, and transmit actions to reducers. Reducers produce new state depending on the action and emit new the state. Store holds the new state until it changes with another action.
An action consists of two parts, a type and payload. Type is required to make reducer enable to distinguish the actions. Therefore type must be unique for each action.
Reducer is the core element in Store and it is the only responsible for changing the state. A reducer takes action and current state as input parameters and return new state according to the function inside it.
(State is immutable in Redux architecture, so reducer does not mutate the state but produce a new state.)
Let’s create a simple reducer with the actions defined previously.
When reducer is called upon a new action, it checks the type of the action and return new state according to action type. As stated previously, reducer must be pure function.
As it is seen obviously, Redux or @ngrx/store is the hardest way to do simple tasks. If you have a simple todo application with Angular, it is not suitable to use @ngrx/store in your application because of heavy overhead in the code. However, it gets more meaningful to implement ngrx/store in your Angular app when the application goes complex.
In the next article we will dive into implementation of @ngrx/store into an Angular application and we will se how to improve performance by using @ngrx/store.