NgRx Store Fundamentals
NgRx Store implements the Redux pattern for Angular: a single immutable state tree, actions that describe changes, and pure reducer functions that produce new state.
Core Concepts
- State — A single immutable object representing application state
- Actions — Plain objects describing what happened
- Reducers — Pure functions that produce new state from actions
- Store — Holds state and dispatches actions
- Selectors — Pure functions that derive state slices
Setting Up NgRx Store
import { provideStore } from '@ngrx/store';
import { provideStoreDevtools } from '@ngrx/store-devtools';
export const appConfig: ApplicationConfig = {
providers: [
provideStore(),
provideStoreDevtools({ maxAge: 25 }),
],
};
Creating Actions
import { createAction, props } from '@ngrx/store';
export const loadUsers = createAction('[Users Page] Load Users');
export const loadUsersSuccess = createAction(
'[Users API] Load Users Success',
props<{ users: User[] }>()
);
export const loadUsersFailure = createAction(
'[Users API] Load Users Failure',
props<{ error: string }>()
);
export const addUser = createAction(
'[Users Page] Add User',
props<{ user: User }>()
);
export const deleteUser = createAction(
'[Users Page] Delete User',
props<{ id: number }>()
);
Dispatching Actions
@Component({
selector: 'app-user-list',
template: `
<button (click)="loadUsers()">Load Users</button>
<p *ngFor="let user of users$ | async">{{ user.name }}</p>
`,
})
export class UserListComponent {
private store = inject(Store);
users$ = this.store.select(state => state.users);
loadUsers(): void {
this.store.dispatch(loadUsers());
}
}
Reading State with Selectors
// In a component
this.store.select(state => state.users).subscribe(users => {
this.users = users;
});
// With async pipe
users$ = this.store.select(state => state.users);
Redux DevTools Integration
NgRx Store DevTools integrates with the Redux DevTools browser extension for time-travel debugging.
Enabling DevTools
import { provideStoreDevtools } from '@ngrx/store-devtools';
export const appConfig: ApplicationConfig = {
providers: [
provideStore(),
provideStoreDevtools({
maxAge: 25, // Number of actions to retain
logOnly: false, // Set true for production
autoPause: true, // Pause recording when extension is not open
}),
],
};
DevTools Features
- Action log — See every dispatched action with payload
- State inspector — View current and previous state
- Time travel — Jump to any previous state
- Diff view — See exactly what changed between actions
Action Naming Conventions
// [Source] Event description
'[Users Page] Load Users' // User initiated from page
'[Users API] Load Users Success' // API response
'[Auth Service] Login Success' // Service event
The source in brackets indicates where the action originated. This helps debugging in DevTools.
Quiz
1. What is an action in NgRx?
2. How do you create type-safe action creators?
3. How do you read state from the store?
Flashcards
Question
What is an NgRx action?
Click to reveal answer
Answer
A plain object with a type field describing what happened. Dispatched to the store.
Question
How do you create action creators?
Click to reveal answer
Answer
createAction('[Source] Event', props<{ payload }>())
Question
How do you read state?
Click to reveal answer
Answer
store.select(state => state.slice) — returns Observable.
Revision Notes
Key Takeaways
- 1. Actions are plain objects describing what happened
- 2. createAction with props() provides type safety
- 3. store.dispatch() sends actions to the store
- 4. store.select() reads state as an Observable
Interview Tips
- • Explain the Redux pattern in Angular context
- • Be ready to describe action naming conventions
- • Mention Redux DevTools for debugging
Cheat Sheet
NgRx Store Cheat Sheet
Setup:
provideStore()
provideStoreDevtools({ maxAge: 25 })
Create actions:
export const loadUsers = createAction('[Users Page] Load Users');
export const loadUsersSuccess = createAction(
'[Users API] Load Users Success',
props<{ users: User[] }>()
);
Dispatch:
this.store.dispatch(loadUsers());
Select state:
this.store.select(state => state.users)