
June 12, 2025 10:33 by
Peter
Managing shared state between components gets more difficult as your Angular application expands. NGXS (pronounced "nexus") offers a simple, intuitive, and powerful state management pattern for Angular apps, based on the principles of Redux but with a more Angular-friendly approach. This post will discuss how to effectively manage application state by configuring and utilizing NGXS.

Why NGXS?
NGXS provides:
- A simple API using decorators and observables.
- Type-safe state and actions.
- Built-in support for plugins (logger, devtools, storage).
- Easy-to-understand state mutation via actions.
Step 1. Install NGXS
Use the Angular CLI to install the NGXS packages:
npm install @ngxs/store --save
Optional DevTools and plugins:
npm install @ngxs/devtools-plugin @ngxs/logger-plugin --save
Step 2. Create a State Model
Create an interface to define your state:
// models/todo.model.ts
export interface Todo {
id: number;
title: string;
completed: boolean;
}
Step 3. Define Actions
Actions are plain classes that represent events in your app.
// actions/todo.actions.ts
export class AddTodo {
static readonly type = '[TODO] Add';
constructor(public payload: string) {}
}
export class ToggleTodo {
static readonly type = '[TODO] Toggle';
constructor(public id: number) {}
}
Step 4. Create the State
Define the NGXS state using the @State() decorator.
// state/todo.state.ts
import { State, Action, StateContext, Selector } from '@ngxs/store';
import { AddTodo, ToggleTodo } from '../actions/todo.actions';
import { Todo } from '../models/todo.model';
@State<Todo[]>({
name: 'todos',
defaults: []
})
export class TodoState {
@Selector()
static getTodos(state: Todo[]) {
return state;
}
@Action(AddTodo)
add({ getState, patchState }: StateContext<Todo[]>, { payload }: AddTodo) {
const state = getState();
const newTodo: Todo = { id: Date.now(), title: payload, completed: false };
patchState([...state, newTodo]);
}
@Action(ToggleTodo)
toggle({ getState, patchState }: StateContext<Todo[]>, { id }: ToggleTodo) {
const state = getState();
const updated = state.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
);
patchState(updated);
}
}
Step 5. Register the State in the App Module
// app.module.ts
import { NgxsModule } from '@ngxs/store';
import { TodoState } from './state/todo.state';
@NgModule({
declarations: [...],
imports: [
NgxsModule.forRoot([TodoState]),
],
bootstrap: [...]
})
export class AppModule {}
Step 6. Use the State in Components
// app.component.ts
import { Store, Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import { TodoState } from './state/todo.state';
import { AddTodo, ToggleTodo } from './actions/todo.actions';
@Component({...})
export class AppComponent {
@Select(TodoState.getTodos) todos$: Observable<Todo[]>;
constructor(private store: Store) {}
addTodo(title: string) {
this.store.dispatch(new AddTodo(title));
}
toggleTodo(id: number) {
this.store.dispatch(new ToggleTodo(id));
}
}
Conclusion
NGXS brings a clean and declarative way to manage state in Angular apps. With actions, selectors, and plugins, it streamlines complex state flows into something more maintainable and scalable. Happy coding !