Akita store vs ngrx angular tutorial

 

Akita Store vs NgRx in Angular: A Tutorial for Managing State

Both Akita and NgRx are popular state management libraries for Angular applications, designed to handle the complexity of application state in a scalable and maintainable way. Akita offers a simpler API compared to NgRx, making it appealing for developers who prefer a more straightforward and less boilerplate-heavy approach.

This tutorial will show you how to set up an Angular project with Akita for state management, comparing it with NgRx in terms of setup and usage.


Why Choose Akita Over NgRx?

  1. Simpler API: Akita’s API is simpler than NgRx, with less boilerplate code and more intuitive syntax.
  2. Out-of-the-box support for entities: Akita has a built-in concept of "entities" to manage collections of items, which is great for dealing with large datasets.
  3. Less opinionated: NgRx enforces strict architectural patterns like effects, reducers, and actions, whereas Akita allows more flexibility.

Setting up Akita in an Angular App

In this tutorial, we will create an Angular app that uses Akita for managing the state of a simple list of items.


1. Prerequisites

Before starting, make sure you have the following installed:

  • Node.js (version 14 or later)
  • Angular CLI (version 12 or later)

2. Create a New Angular Project

If you haven't already, create a new Angular project:

bash
ng new akita-tutorial cd akita-tutorial

3. Install Akita

To install Akita, run the following command:

bash
npm install @datorama/akita

This will install the Akita store along with its utilities.


4. Set Up Akita Store

For this example, we will create a store for managing a list of items. Let’s define the basic structure of the store.

Step 1: Create an Entity Store

Create a new file for the store, items.store.ts, inside the src/app/store folder.

typescript
// src/app/store/items.store.ts import { Store, StoreConfig } from '@datorama/akita'; export interface Item { id: number; name: string; } export interface ItemsState { items: Item[]; } @StoreConfig({ name: 'items' }) export class ItemsStore extends Store<ItemsState> { constructor() { super({ items: [] }); } }
  • StoreConfig: This decorator tells Akita to use a specific name for the store (in this case, "items").
  • super({ items: [] }) initializes the store with an empty list of items.

Step 2: Create a Query

In Akita, queries are used to read the data from the store. Let's create a query for accessing the items in the store.

typescript
// src/app/store/items.query.ts import { Query } from '@datorama/akita'; import { Injectable } from '@angular/core'; import { ItemsStore, ItemsState } from './items.store'; @Injectable({ providedIn: 'root' }) export class ItemsQuery extends Query<ItemsState> { constructor(protected store: ItemsStore) { super(store); } // Getter for items get items$() { return this.select(state => state.items); } }
  • select(state => state.items) selects the items from the store’s state and returns it as an observable.

Step 3: Create a Service to Handle Logic

We will also create a service to manage the logic, such as adding new items to the store.

typescript
// src/app/store/items.service.ts import { Injectable } from '@angular/core'; import { ItemsStore } from './items.store'; @Injectable({ providedIn: 'root' }) export class ItemsService { constructor(private itemsStore: ItemsStore) {} addItem(name: string) { const item = { id: Math.random(), name }; // Simple random ID generation for demo this.itemsStore.update(state => ({ items: [...state.items, item] })); } }
  • addItem: This method will add a new item to the store’s state.

5. Integrate the Store in the Angular Module

Now, let’s integrate the store into the Angular module by importing it into the AppModule.

typescript
// src/app/app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ItemsStore } from './store/items.store'; import { ItemsService } from './store/items.service'; import { ItemsQuery } from './store/items.query'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule], providers: [ItemsStore, ItemsService, ItemsQuery], bootstrap: [AppComponent] }) export class AppModule {}

6. Create a Component to Display and Add Items

Now, let’s create a component that will use the store to display the list of items and add new ones.

typescript
// src/app/app.component.ts import { Component } from '@angular/core'; import { ItemsService } from './store/items.service'; import { ItemsQuery } from './store/items.query'; @Component({ selector: 'app-root', template: ` <div> <h1>Item List</h1> <ul> <li *ngFor="let item of items$ | async">{{ item.name }}</li> </ul> <input [(ngModel)]="newItem" placeholder="Enter item name" /> <button (click)="addItem()">Add Item</button> </div> `, styles: [] }) export class AppComponent { newItem: string = ''; items$ = this.itemsQuery.items$; constructor( private itemsService: ItemsService, private itemsQuery: ItemsQuery ) {} addItem() { if (this.newItem.trim()) { this.itemsService.addItem(this.newItem); this.newItem = ''; } } }

Explanation:

  • items$: The observable that provides the current list of items from the store.
  • addItem(): This method triggers the service to add a new item to the store.

7. Set Up the Template for AppComponent

Ensure that you have FormsModule imported to use ngModel for two-way data binding in your component.

typescript
// src/app/app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; // <-- Import FormsModule import { ItemsStore } from './store/items.store'; import { ItemsService } from './store/items.service'; import { ItemsQuery } from './store/items.query'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, FormsModule], // <-- Include FormsModule here providers: [ItemsStore, ItemsService, ItemsQuery], bootstrap: [AppComponent] }) export class AppModule {}

8. Run the Application

Finally, run your Angular app with the following command:

bash
ng serve

Visit http://localhost:4200 in your browser, and you should see a form to add items, and the list of added items below the input.


Conclusion

This tutorial demonstrated how to set up and use Akita in an Angular application to manage state. The steps included:

  • Installing and setting up Akita.
  • Creating a store, query, and service.
  • Using the store in an Angular component.
  • Running the application to see state changes.

Akita vs NgRx

While NgRx is a powerful state management solution based on Redux, Akita offers a more intuitive, less boilerplate-heavy approach for managing state. Akita’s support for entities makes it especially useful when dealing with collections of data, whereas NgRx enforces a more structured approach with actions, reducers, and effects.

Next Steps:

  • Explore more advanced Akita features such as store persistence and queries with filters.
  • Learn how to implement Akita plugins for additional functionalities.
  • You can also explore how to integrate Akita with Angular’s Router for managing state across different routes.

Comments

Popular posts from this blog

PrimeNG tutorial with examples using frequently used classes

Docker and Kubernetes Tutorials and QnA

Building strong foundational knowledge in frontend development topics