Questions
How do you do state management in Angular?
The Scenario
You are a frontend engineer at a social media company. You are building a new single-page application (SPA) that has a complex state that needs to be shared across multiple components.
You are not sure whether to use a simple service or a more advanced state management library like NgRx.
The Challenge
Explain how you would do state management in Angular. What are the different state management patterns that you would use, and what are the trade-offs between them?
A junior engineer might try to solve this problem by using a service with a `BehaviorSubject`. This would work for a small application, but it would not be a very scalable or maintainable solution for a large application.
A senior engineer would know that a state management library like NgRx is the perfect tool for this job. They would be able to explain the different state management patterns and would have a clear plan for how to use NgRx to manage the state of a large application.
Step 1: Understand the Different State Management Patterns
| Pattern | Description | Pros | Cons |
|---|---|---|---|
| Simple Service | A simple service with a BehaviorSubject that can be used to store and share the state. | Easy to understand and implement. | Can become difficult to maintain for a large application. |
| NgRx | A state management library for Angular applications. It is inspired by Redux and provides a more structured and maintainable way to manage the state of a large application. | Provides a more structured and maintainable way to manage the state of a large application. | Can be more complex to set up than a simple service. |
Step 2: Choose the Right Tool for the Job
For our use case, we should use NgRx. This is because we are building a large application with a complex state that needs to be shared across multiple components.
Step 3: Code Examples
Here’s how we can use NgRx to manage the state of our application:
1. Define the state, actions, and reducer:
// app.state.ts
export interface AppState {
count: number;
}
// app.actions.ts
import { createAction } from '@ngrx/store';
export const increment = createAction('[Counter] Increment');
// app.reducer.ts
import { createReducer, on } from '@ngrx/store';
import { increment } from './app.actions';
export const initialState = 0;
const _counterReducer = createReducer(
initialState,
on(increment, (state) => state + 1)
);
export function counterReducer(state, action) {
return _counterReducer(state, action);
}2. Use the store in a component:
import { Component } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { increment } from './app.actions';
import { Observable } from 'rxjs';
@Component({
selector: 'my-counter',
template: `
<p>{{ count$ | async }}</p>
<button (click)="increment()">Increment</button>
`
})
export class MyCounterComponent {
count$: Observable<number>;
constructor(private store: Store<{ count: number }>) {
this.count$ = store.pipe(select('count'));
}
increment() {
this.store.dispatch(increment());
}
} Practice Question
You want to be able to access a piece of derived state from your store. Which of the following would you use?