State Management in Angular using Akita
AngularInDepth is moving away from Medium. More recent articles are hosted on the new platform inDepth.dev. Thanks for being part of indepth movement!
In this article, we’ll explain the state management concept and how Akita helps us to facilitate the data flow in the application by managing it.
A state machine is any device that stores the status of something at a given time and can operate on input to change the status and/or cause an action or output to take place for any given change. — The State Machine
Simply put, it stores the state of any form of data and manages the state transition based on current state and action.
Why State Management is Important?
Web-apps are getting richer and more complex. Managing state is exponentially harder than it used to be.
Different parts of an application have different responsibilities, and those (components, directives, etc.) are segregated across many different files, but they all need to reflect the same underlying state.
A state management library gives you a convenient way to:
- Model your application state
- Derive computed values from it
- Monitor it for changes
It gives us many benefits like handling normalized data (redundant models can be avoided), immutability and organized state transition, time travel ability, etc.
Introduction to Akita
Akita is a state management pattern, built on top of RxJS and based on object-oriented design principles.
Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.
Before we dive in, let’s examine Akita’s building blocks:
The Model
The general representation of the data model which the store is going to manage.
The Store
A Store is like a warehouse, where the data model is going to be stored. You can execute all the DML (Data Manipulation Language) with the help of Akita built-in store’s methods like add()
, update()
, delete()
, setActive()
, setError()
, etc.
The Query
Simply database queries, which helps querying the store. The query results are available in two forms — reactive queries and synchronize queries.
You can run all the DDL (Data Definition Language) with the help of Akita built-in query’s methods like select()
, selectAll()
, selectEntity()
, selectCount()
, selectActive()
, etc.
Two types of Stores
The Basic Store — when our model doesn’t represent a collection of entities, e.g., session, UI states, etc.
The Entity Store — when we need to maintain a collection of entities e.g., domain model, e.g., employee, student, etc.
Time to Code
We’ll build a student dashboard application with Akita and learn how to create and use both a simple and entity store.
Folder Structure
Here is how Akita recommends structuring the project, for the sake of maintaining modularity and order.
An additional data service is recommended only on enterprise applications.
Note that Akita offers a CLI tool or schematics, enabling you to generate stores based on the specifications quickly.
Let’s continue and create the session state:
Session Store
To maintain the active user, we need to create a session
table, i.e., store.
Usually data model and create factory functions are the part of the model file declaration (e.g., session.model.ts) since we use a basic store, we don’t need separate model file instead, we keep our model along with store file.
As mentioned earlier you can see some of the DML operations that are performing as a part of the store.
Let’s create the session query:
The select()
methods selects a slice from the store. We can see how we can encapsulate more complex queries inside the Query
class, leaving our component unaware of the data source.
The Query
class is handling the DDL operations. In the above code, we can see an example of a reactive query like isLoggedIn$
and synchronize query like isLoggedIn()
.
Let’s visualize the current state with the help of Akita’s dev-tools:
Student Store
Since a Student
is a domain model we know that we need to maintain a collection of entities, so the choice of the store here is EntityStore.
We start by defining the Student
interface and a factory function that knows how to create a student. We’re using Akita’s guid()
method to generate globally unique id.
To create an EntityStore
we need to define the store’s interface. In our case, we can make do with extending the EntityState
from Akita, providing it with the Student
Entity type.
Let’s create the student query:
Let’s create the student service:
Asynchronous logic and update calls should be encapsulated in services.
The components can use StudentService
and StudentQuery
to handle all the DML and DDL activities needed for the model.
Here’s the final state of the application:
Conclusion
In short, Akita will help to manage all your data at once place and give you the strong abstraction on handling each operation either DML or DDL operations which we thought to perform on the data.
Use Akita it will make your life easier.
Find the complete code and demo.
If you enjoy the article, give some claps to motivate ✋✋✋
Thanks for Reading! Happy Akita!!!