WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Angular · Expert · question 68 of 100

How do you implement advanced state management patterns in Angular applications using libraries like Akita or MobX?

📕 Buy this interview preparation book: 100 Angular questions & answers — PDF + EPUB for $5

Advanced state management patterns can significantly improve the maintainability and robustness of Angular applications. Two popular libraries for state management are Akita and MobX. Each has its approach and philosophy. Let’s discuss how to implement these state management patterns in Angular applications using Akita and MobX.

## Akita

Akita is a reactive state management library that emphasizes simplicity and built on top of Observables. It works with both Angular and non-Angular projects. Akita uses the concepts of a "store," "query," and "service" to manage state.

### Steps to implement Akita in Angular:

1. **Install Akita**:

Install Akita using your package manager of choice:

npm install @datorama/akita

2. **Create a state interface**:

Define the shape of your state by creating a state interface. For example, if you wanted to manage a list of todos, you’d create a ‘Todo‘ interface:

export interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

3. **Create a store**:

A store represents a specific state in your application. To create a store, extend the ‘Store‘ class from Akita and provide a default state as the initial value.

import { Store, StoreConfig } from '@datorama/akita';
import { Todo } from './todo.model';

export interface TodosState {
  todos: Todo[];
}

export function createInitialState(): TodosState {
  return {
    todos: []
  };
}

@Injectable({ providedIn: 'root' })
@StoreConfig({ name: 'todos' })
export class TodosStore extends Store<TodosState> {
  constructor() {
    super(createInitialState());
  }
}

4. **Create a query**:

Queries are responsible for retrieving data from a store. To create a query, extend the ‘Query‘ class from Akita.

import { Query } from '@datorama/akita';
import { TodosState, TodosStore } from './todos.store';
import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class TodosQuery extends Query<TodosState> {
  constructor(protected store: TodosStore) {
    super(store);
  }
}

5. **Create a service**:

Services are responsible for updating the store. They are optional in Akita, but they help enforce the separation of concerns in your application.

import { Injectable } from '@angular/core';
import { TodosStore } from './todos.store';

@Injectable({ providedIn: 'root' })
export class TodosService {
  constructor(private todosStore: TodosStore) {}

  add(todo: Todo): void {
    this.todosStore.add(todo);
  }

  update(id: number, partial: Partial<Todo>): void {
    this.todosStore.update(id, partial);
  }

  remove(id: number): void {
    this.todosStore.remove(id);
  }
}

6. **Use the service, store, and query in a component**:

Now, you can utilize the store, query, and service to manage state in your Angular components.

import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { TodosService } from './state/todos.service';
import { TodosQuery } from './state/todos.query';
import { Todo } from './state/todo.model';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  todos$: Observable<Todo[]> = this.todosQuery.selectAll();

  constructor(private todosService: TodosService, private todosQuery: TodosQuery) {}

  addTodo(title: string): void {
    const newTodo: Todo = {
      id: Date.now(),
      title,
      completed: false
    };
    this.todosService.add(newTodo);
  }

  toggleTodo(id: number, completed: boolean): void {
    this.todosService.update(id, { completed });
  }

  removeTodo(id: number): void {
    this.todosService.remove(id);
  }
}

## MobX

MobX is another state management library that utilizes reactive programming to manage state. It is less Angular-centric and can be used with other frontend frameworks.

### Steps to implement MobX in Angular:

1. **Install MobX, mobx-angular, and mobx-angularjs-bindings**:

Install MobX and the accompanying Angular bindings:

npm install mobx mobx-angular mobx-angularjs-bindings

2. **Create a store**:

A store in MobX is simply a TypeScript class with observable properties, computed properties, and actions that manipulate the state.

import { makeAutoObservable } from 'mobx';

export class TodoStore {
  todos: Todo[] = [];

  constructor() {
    makeAutoObservable(this);
  }

  // Computed property (mobx will cache the result until dependencies change)
  get incompleteTodos() {
    return this.todos.filter((t) => !t.completed);
  }

  // Action
  addTodo(title: string) {
    const newTodo: Todo = {
      id: Date.now(),
      title,
      completed: false
    };
    this.todos.push(newTodo);
  }

  // Action
  toggleTodo(id: number) {
    const todo = this.todos.find((t) => t.id === id);
    if (todo) {
      todo.completed = !todo.completed;
    }
  }

  // Action
  removeTodo(id: number) {
    this.todos = this.todos.filter((t) => t.id !== id);
  }
}

3. **Create and provide the store instance**:

Update your AppModule to provide a new TodoStore instance:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { MobxAngularModule } from 'mobx-angular';
import { AppComponent } from './app.component';
import { TodoStore } from './stores/todo.store';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, MobxAngularModule],
  providers: [{ provide: TodoStore, useValue: new TodoStore() }],
  bootstrap: [AppComponent]
})
export class AppModule {}

4. **Use the store in a component**:

In your components, you can now use the ‘*mobxAutorun‘ directive to bind observables and execute actions.

import { Component } from '@angular/core';
import { TodoStore } from './stores/todo.store';
import { Todo } from './stores/todo.model';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  newTodoTitle: string;

  constructor(public todoStore: TodoStore) {}

  addTodo() {
    this.todoStore.addTodo(this.newTodoTitle);
    this.newTodoTitle = '';
  }

  toggleTodo(id: number) {
    this.todoStore.toggleTodo(id);
  }

  removeTodo(id: number) {
    this.todoStore.removeTodo(id);
  }
}

And the corresponding component template:

<div>
  <input [(ngModel)]="newTodoTitle" />
  <button (click)="addTodo()">Add Todo</button>
</div>
<ul *mobxAutorun>
  <li *ngFor="let todo of todoStore.todos" [class.completed]="todo.completed">
    <input type="checkbox" [checked]="todo.completed" (change)="toggleTodo(todo.id)" />
    {{ todo.title }}
    <button (click)="removeTodo(todo.id)">X</button>
  </li>
</ul>
{{ todoStore.incompleteTodos.length }} incomplete todos

Both Akita and MobX provide powerful state management solutions for Angular applications. Choose the one that best fits your project’s needs and coding style. If you prefer a more structured and declarative approach, go with Akita. If you want a more minimalistic, reactive-oriented library, MobX may be a better fit.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Angular interview — then scores it.
📞 Practice Angular — free 15 min
📕 Buy this interview preparation book: 100 Angular questions & answers — PDF + EPUB for $5

All 100 Angular questions · All topics