State Management in Angular
State management in Angular means managing and sharing application data across components in a predictable and maintainable way.
Examples of state:
-
Logged-in user information
-
Shopping cart items
-
Selected filters
-
API response data
-
Theme settings
-
Form data
Why State Management is Needed
Without proper state management:
-
Components become tightly coupled
-
Data duplication happens
-
Communication becomes difficult
-
Debugging becomes harder
-
Large applications become difficult to maintain
State management helps:
-
Centralize data
-
Make data flow predictable
-
Improve scalability
-
Simplify debugging
-
Avoid unnecessary API calls
Different Ways to Handle State Management in Angular
1. Local Component State
Used for:
-
Small UI-related data
-
Temporary values
Example:
export class CounterComponent {
count = 0;
increment() {
this.count++;
}
}
Best for:
-
Button toggles
-
Modal visibility
-
Form field values
Interview Point:
Local state is suitable when data is needed only inside a single component.
2. Parent-Child Communication
Using:
-
@Input() -
@Output()
Example:
Child Component
@Input() userName!: string;
@Output() save = new EventEmitter<string>();
Parent Component
<app-child
[userName]="name"
(save)="onSave($event)">
</app-child>
Best for:
-
Directly related components
Limitation:
-
Becomes difficult in deeply nested component trees
3. Shared Service with RxJS (Most Common)
This is the most common Angular interview answer for medium applications.
Angular services can act as a central store.
Usually implemented using:
-
BehaviorSubject -
Subject -
ReplaySubject
Using BehaviorSubject for State Management
Service
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
private userSubject = new BehaviorSubject<any>(null);
user$ = this.userSubject.asObservable();
setUser(user: any) {
this.userSubject.next(user);
}
}
Component Updating State
constructor(private userService: UserService) {}
login() {
this.userService.setUser({
name: 'Sampath'
});
}
Component Reading State
constructor(private userService: UserService) {}
ngOnInit() {
this.userService.user$.subscribe(user => {
console.log(user);
});
}
Why BehaviorSubject is Commonly Used
Because it:
-
Stores the latest value
-
Sends the latest value to new subscribers
-
Works reactively
Interview Statement:
BehaviorSubjectis commonly used in Angular services for lightweight reactive state management.
4. NgRx (Redux Pattern)
For large enterprise applications, Angular commonly uses NgRx.
NgRx follows:
-
Single source of truth
-
Immutable state
-
Unidirectional data flow
NgRx Architecture
Main concepts:
| Concept | Purpose |
|---|---|
| Store | Central state container |
| Actions | Describe events |
| Reducers | Update state |
| Selectors | Read state |
| Effects | Handle async operations |
NgRx Flow
Component
↓
Dispatch Action
↓
Reducer updates Store
↓
Selector reads updated state
↓
UI updates
Example of NgRx Action
export const loadUsers = createAction('[User] Load Users');
Example Reducer
export const userReducer = createReducer(
initialState,
on(loadUsersSuccess, (state, { users }) => ({
...state,
users
}))
);
Advantages of NgRx
Advantages
-
Predictable state flow
-
Excellent for large apps
-
Easier debugging
-
Time-travel debugging
-
Better scalability
-
Centralized state
Disadvantages
-
Boilerplate code
-
Learning curve
-
Overkill for small projects
5. NGXS and Akita
Other Angular state libraries:
-
NGXS
-
Akita
They provide:
-
Simpler syntax than NgRx
-
Less boilerplate
-
Easier learning curve
When to Use What
| Application Size | Recommended Approach |
|---|---|
| Small | Component state |
| Medium | Service + RxJS |
| Large Enterprise | NgRx |
| Very Complex | NgRx with Effects |
Important RxJS Concepts in State Management
Interviewers often ask these together.
Subject
No initial value.
BehaviorSubject
Has initial value and emits latest value.
ReplaySubject
Replays previous emitted values.
Best Practices
Keep State Minimal
Store only necessary data.
Avoid Duplicate State
Single source of truth.
Use Immutable Updates
Good:
return {
...state,
users: [...users]
};
Bad:
state.users.push(user);
Use Async Pipe
Prefer:
<div>{{ user$ | async }}</div>
Instead of manual subscriptions.
Benefits:
-
Automatic unsubscribe
-
Cleaner code
Common Interview Questions
Q1: Why use state management?
Answer:
To manage shared application data predictably, avoid prop drilling, improve scalability, and simplify debugging.
Q2: Difference between Subject and BehaviorSubject?
| Subject | BehaviorSubject |
|---|---|
| No initial value | Requires initial value |
| New subscribers don't get previous value | New subscribers receive latest value |
Q3: When would you choose NgRx?
Answer:
For large enterprise applications with complex shared state, multiple async operations, and many interacting components.
Q4: What is a single source of truth?
Answer:
Maintaining application state in one centralized store so all components use the same consistent data.
Real-Time Example
E-Commerce Application
State includes:
-
Logged-in user
-
Cart items
-
Wishlist
-
Product filters
-
Orders
Possible approach:
-
Small app → Service + BehaviorSubject
-
Enterprise app → NgRx
Interview Summary
A strong interview answer:
In Angular, state management is used to manage and share application data efficiently across components. For small applications, local component state and
@Input/@Outputare sufficient. For medium applications, shared services with RxJSBehaviorSubjectare commonly used. For large enterprise applications, libraries like NgRx provide centralized and predictable state management using actions, reducers, selectors, and effects.
