
Existing member? Log in and continue learning

See if you like it, start the course for free!

Unlock full course by purchasing a membership
State Management Libraries
State Management Libraries
The state management approach we have looked at is something that can scale well — I think it also adheres to the idea of declarative and reactive code more closely than many other state management libraries.
There is no specific reasons that you have to use a state management library — but certain libraries might provide you with certain conveniences or use a particular style that you like. Perhaps you join a team where state is handled using a state management library.
It is not a goal of this course to cover how to integrate various state management libraries, but I do want to give you an idea of some of the popular options out there that you might come across and what their general philosophy is.
SignalStore
NgRx SignalStore (not to be confused with other libraries offered by NgRx) is quite new, but is quickly becoming a sort of defacto state management solution for signals in the Angular world.
A basic implementation looks like this:
import { signalStore, withState } from '@ngrx/signals';import { Book } from './book.model';
type BooksState = { books: Book[]; isLoading: boolean; filter: { query: string; order: 'asc' | 'desc' };};
const initialState: BooksState = { books: [], isLoading: false, filter: { query: '', order: 'asc' },};
export const BooksStore = signalStore( withState(initialState));
This BooksStore
can then be injected wherever you need to use it:
import { Component, inject } from '@angular/core';import { BooksStore } from './books.store';
@Component({ providers: [BooksStore],})export class BooksComponent { readonly store = inject(BooksStore);}
Alternatively, so that you wouldn’t have to add it to the providers
of a
particular component, you can provide it globally like this:
export const BooksStore = signalStore( { providedIn: 'root' }, withState(initialState));
At a basic level, we pass whatever state we want to keep track of to the store
using withState
. We will then be given signals for all of that state,
including the nested state like query
and order
, e.g:
console.log(store.books())console.log(store.isLoading())console.log(store.filter.query())console.log(store.filter.order())
As well as withState
, SignalStore provides many other features that provide
you a great deal of control over how to use and update your state.
StateAdapt
StateAdapt is a very new state management library, which does make it risky to use. However, I wanted to give it a quick special mention because I think it is the state management library that deals with the idea of coding reactive/declaratively the best.
In general, the philosophy is very much the same as the approach we are using — that is due in large part to the fact that I was heavily inspired by it when deciding on the approach we are using in this course.
The API to use it is perhaps a bit more confronting than what we have covered, but it offers a bunch of extra features.
signalSlice
Full disclosure: I co-created this utility and designed it around the way I like to think about state, so naturally this is a solution I am biased toward.
signalSlice is a lightweight state utility that is designed around similar ideas to those we have already discussed in terms of declarative code.
A basic implementation looks like this:
initialState = { checklists: []};
state = signalSlice({ initialState: this.initialState, sources: [this.loadChecklists$], actionSources: { add: (state, action$: Observable<AddChecklist>) => action$.pipe( map((checklist) => ({ checklists: [...state().checklists, checklist], })), ), }});
Thanks for checking out the preview of this lesson!
You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).