Skip to content
intermediate Phase 12 · NgRx State Management

Selectors for Reading State

Derive and memoize slices of state for components.

40m
0 problems
Topic Progress 0%

Creating Selectors

Selectors are pure functions that derive and memoize state slices. They only recompute when their inputs change.

Basic Selector

import { createFeatureSelector, createSelector } from '@ngrx/store';

// Feature selector
export const selectUserState = createFeatureSelector<UserState>('users');

// Simple selectors
export const selectUsers = createSelector(
  selectUserState,
  state => state.users
);

export const selectLoading = createSelector(
  selectUserState,
  state => state.loading
);

export const selectError = createSelector(
  selectUserState,
  state => state.error
);

Composing Selectors

export const selectActiveUsers = createSelector(
  selectUsers,
  users => users.filter(u => u.isActive)
);

export const selectUserCount = createSelector(
  selectUsers,
  users => users.length
);

export const selectUsersWithLoading = createSelector(
  selectUsers,
  selectLoading,
  (users, loading) => ({ users, loading })
);

Using Selectors in Components

@Component({
  selector: 'app-user-list',
  template: `
    <div *ngIf="loading$ | async">Loading...</div>
    <p *ngFor="let user of users$ | async">{{ user.name }}</p>
  `,
})
export class UserListComponent {
  private store = inject(Store);

  users$ = this.store.select(selectUsers);
  loading$ = this.store.select(selectLoading);
}

Memoization and Performance

Selectors memoize results — they only recompute when their input selectors produce new values.

How Memoization Works

export const selectActiveUsers = createSelector(
  selectUsers,           // Input selector
  users => users.filter(u => u.isActive)  // Projector function
);
  1. selectUsers runs and returns users
  2. If users reference is the same as last time, selectActiveUsers returns the cached result
  3. If users reference changed, the projector function runs again

Selector with Parameters

export const selectUserById = (id: number) => createSelector(
  selectUsers,
  users => users.find(u => u.id === id)
);

// Usage
this.user$ = this.store.select(selectUserById(42));

Converting Selectors to Signals

import { toSignal } from '@angular/core/rxjs-interop';

@Component({
  selector: 'app-user-list',
  template: `<p *ngFor="let user of users()">{{ user.name }}</p>`,
})
export class UserListComponent {
  private store = inject(Store);

  users = toSignal(this.store.select(selectUsers), { initialValue: [] });
}

Selector Best Practices

  1. Keep selectors small — Compose from smaller selectors
  2. Memoize expensive computations — createSelector caches results
  3. Use feature selectors — createFeatureSelector for state slices
  4. Avoid logic in components — Move derivation to selectors

Quiz

1. What does createSelector do?

Question 1 options

2. How do you convert a selector to a signal?

Question 2 options

3. What is a feature selector?

Question 3 options

Flashcards

Question

What does createSelector do?

Answer

Creates a memoized selector. Only recomputes when inputs change.

Question

How do you convert a selector to a signal?

Answer

toSignal(store.select(selector), { initialValue: [] })

Question

What is a feature selector?

Answer

createFeatureSelector<State>('name') — selects a top-level state slice.

Revision Notes

Key Takeaways

  • 1. createSelector memoizes derived state
  • 2. Compose selectors for complex derivations
  • 3. toSignal converts selectors to signals
  • 4. Feature selectors select top-level state slices

Interview Tips

  • • Explain selector memoization
  • • Be ready to describe selector composition
  • • Mention toSignal for signal-based reads

Cheat Sheet

Selectors Cheat Sheet

Feature selector:

export const selectUserState = createFeatureSelector<UserState>('users');

Simple selector:

export const selectUsers = createSelector(
  selectUserState,
  state => state.users
);

Composed selector:

export const selectActiveUsers = createSelector(
  selectUsers,
  users => users.filter(u => u.isActive)
);

To signal:

users = toSignal(this.store.select(selectUsers), { initialValue: [] });

Continue Learning

Before You Start

Related Reading