Angular NgRx Selectors
Learn Angular NgRx Selectors with createSelector, memoization, feature selectors, composed selectors, Signals integration, enterprise architecture, best practices, and interview questions.
In NgRx, components should never read the Store directly.
Instead, they use Selectors, which provide a clean, reusable, and efficient way to retrieve data from the Store.
Selectors are one of the most powerful features of NgRx because they:
- Encapsulate state access
- Improve performance through memoization
- Prevent duplicate logic
- Support derived state
- Make applications easier to test
- Improve maintainability
In enterprise applications, almost every component interacts with the Store through Selectors.
Table of Contents
- What are Selectors?
- Why Use Selectors?
- Selector Architecture
- Feature Selectors
- createSelector()
- Memoization
- Derived State
- Composing Selectors
- Selectors with Signals
- Enterprise Banking Example
- Performance Best Practices
- Common Mistakes
- Top 10 Interview Questions
- Summary
What are Selectors?
A Selector is a pure function that retrieves a portion of application state from the Store.
Instead of components navigating the Store structure,
components simply request the data they need.
Example
customers$ = this.store.select(selectCustomers);
The component doesn't know how the Store is organized.
Why Use Selectors?
Without Selectors
- Components access Store structure directly
- Duplicate filtering logic
- Harder maintenance
- Difficult refactoring
With Selectors
- Encapsulated state access
- Reusable logic
- Memoized results
- Cleaner components
- Better performance
Selector Architecture
flowchart LR
Store
Store --> FeatureSelector
FeatureSelector --> Selector
Selector --> Component
Component --> UI
Store Read Flow
flowchart TD
Store
Store --> Selector
Selector --> Observable
Observable --> Component
Component --> Template
Feature Selectors
A Feature Selector retrieves an entire feature state.
Example
export interface CustomerState {
customers: Customer[];
loading: boolean;
}
Create Feature Selector
import { createFeatureSelector } from '@ngrx/store';
export const selectCustomerState =
createFeatureSelector<CustomerState>(
'customer'
);
This becomes the foundation for other selectors.
createSelector()
Most Selectors are created using createSelector().
Example
import { createSelector } from '@ngrx/store';
export const selectCustomers =
createSelector(
selectCustomerState,
state => state.customers
);
Components can now retrieve customer data without understanding the Store structure.
Selector Flow
flowchart LR
Store
Store --> FeatureSelector
FeatureSelector --> createSelector
createSelector --> Component
Reading Data
Component
customers$ =
this.store.select(
selectCustomers
);
Template
<ul>
<li
*ngFor="let customer of customers$ | async">
{{ customer.name }}
</li>
</ul>
Memoization
Selectors are memoized.
This means Angular recalculates the selector only when its input state changes.
Benefits
- Better performance
- Fewer computations
- Faster rendering
- Reduced CPU usage
Memoization Architecture
flowchart LR
StoreChange
StoreChange --> Selector
Selector --> Cache
Cache --> Component
If the input state remains the same,
the cached value is returned.
Derived State
Selectors can compute values instead of storing them.
Example
export const selectCustomerCount =
createSelector(
selectCustomers,
customers => customers.length
);
Instead of storing:
customerCount
inside the Store,
compute it when needed.
Derived Data Examples
Useful derived values
- Total Orders
- Customer Count
- Account Balance
- Shopping Cart Total
- Active Users
- Filtered Products
Composing Selectors
Selectors can be combined.
Example
export const selectPremiumCustomers =
createSelector(
selectCustomers,
customers =>
customers.filter(
customer => customer.isPremium
)
);
Another example
export const selectPremiumCount =
createSelector(
selectPremiumCustomers,
customers => customers.length
);
This keeps logic reusable and modular.
Composed Selector Architecture
flowchart TD
Store
Store --> selectCustomers
selectCustomers --> PremiumCustomers
PremiumCustomers --> PremiumCount
PremiumCount --> Component
Parameterized Selectors
Selectors can accept parameters using factory functions.
export const selectCustomerById =
(id: number) =>
createSelector(
selectCustomers,
customers =>
customers.find(
customer => customer.id === id
)
);
Usage
customer$ =
this.store.select(
selectCustomerById(101)
);
Selectors with Signals
Modern Angular integrates Selectors with Signals.
import { toSignal } from '@angular/core/rxjs-interop';
customers =
toSignal(
this.store.select(
selectCustomers
)
);
Template
@for (
customer of customers();
track customer.id
) {
<div>
{{ customer.name }}
</div>
}
Benefits
- Cleaner templates
- Signal reactivity
- Automatic updates
Signals Architecture
flowchart LR
Store
Store --> Selector
Selector --> Signal
Signal --> Component
Component --> UI
Enterprise Banking Example
Banking Dashboard
Store
- Customers
- Accounts
- Cards
- Loans
- Transactions
- Investments
Selectors
- Active Accounts
- Total Balance
- Premium Customers
- Recent Transactions
- Loan Summary
Architecture
flowchart TD
Store
Store --> AccountSelector
Store --> CustomerSelector
Store --> TransactionSelector
AccountSelector --> Dashboard
CustomerSelector --> Dashboard
TransactionSelector --> Dashboard
Benefits
- Centralized business logic
- Better reuse
- Excellent performance
- Easier testing
Folder Structure
store/
├── selectors/
│
├── customer.selectors.ts
│
├── account.selectors.ts
│
├── auth.selectors.ts
│
├── order.selectors.ts
│
└── index.ts
Performance Best Practices
| Practice | Benefit |
|---|---|
| Always use Selectors | Encapsulation |
| Use Feature Selectors | Better modularity |
| Derive values | Less duplicate state |
| Compose Selectors | Better reuse |
| Use memoization | Improved performance |
| Convert to Signals | Cleaner templates |
| Use OnPush | Better rendering |
| Keep Selectors pure | Predictable behavior |
Common Mistakes
Accessing Store Directly
❌ Wrong
this.store.customer.customers
Always use Selectors.
Storing Derived Data
❌ Wrong
Store:
customerCount
Better
customers.length
inside a Selector.
Business Logic in Components
❌ Wrong
customers$
.pipe(
map(customers =>
customers.filter(
customer => customer.active
)
)
);
Move the filtering into a Selector.
Side Effects in Selectors
Selectors should never:
- Call APIs
- Update state
- Dispatch Actions
Selectors are pure functions.
Large Selectors
Split complex logic into smaller composed Selectors.
Feature Selector vs Selector
| Feature | Feature Selector | Selector |
|---|---|---|
| Reads Feature State | ✅ | ❌ |
| Reads Specific Data | ❌ | ✅ |
| Uses createFeatureSelector | ✅ | ❌ |
| Uses createSelector | ❌ | ✅ |
| Composable | Limited | Excellent |
Advantages
| Feature | Benefit |
|---|---|
| Memoization | Faster performance |
| Encapsulation | Cleaner components |
| Derived State | Less duplicate data |
| Composition | Better reuse |
| Signals Integration | Modern Angular support |
| Enterprise Ready | Highly scalable |
Top 10 Selectors Interview Questions
1. What is a Selector in NgRx?
Answer
A Selector is a pure function that retrieves and derives state from the NgRx Store without modifying it.
2. Why should components use Selectors?
Answer
Selectors encapsulate Store access, improve reusability, enable memoization, and keep components simple and maintainable.
3. What is a Feature Selector?
Answer
A Feature Selector retrieves an entire feature slice of state and serves as the starting point for creating more specific selectors.
4. What does createSelector() do?
Answer
createSelector() creates memoized selectors that efficiently compute and return specific pieces of application state.
5. What is memoization?
Answer
Memoization caches the previous selector result and recomputes it only when its input state changes, reducing unnecessary calculations.
6. What is derived state?
Answer
Derived state is data calculated from existing Store values, such as totals, counts, filtered lists, or summaries, instead of storing duplicate values.
7. Can Selectors be composed?
Answer
Yes. Multiple selectors can be combined to build more advanced selectors while keeping logic modular and reusable.
8. Can Selectors work with Signals?
Answer
Yes. Selector Observables can be converted into Signals using toSignal() for a more modern and reactive template experience.
9. What are common Selector mistakes?
Answer
- Accessing Store directly
- Storing derived data
- Adding business logic to components
- Performing side effects in selectors
- Creating overly complex selectors
10. What are Selector best practices?
Answer
Use Feature Selectors, derive values instead of storing duplicates, compose selectors for reuse, keep selectors pure, leverage memoization, and integrate them with Signals where appropriate.
Interview Cheat Sheet
| Requirement | Recommended Solution |
|---|---|
| Read Store State | Selector |
| Read Feature State | Feature Selector |
| Derived Values | createSelector() |
| Performance | Memoization |
| Reusable Logic | Composed Selectors |
| UI Reactivity | Signals |
| Change Detection | OnPush |
| Global State | NgRx Store |
| Async Work | Effects |
| Enterprise Apps | Feature Selectors + Memoized Selectors |
Summary
NgRx Selectors provide the recommended way to read application state by encapsulating Store access behind reusable, memoized, and composable functions. They simplify components, avoid duplicate business logic, and improve performance through memoization. In modern Angular applications, Selectors are often combined with Signals to deliver a clean, reactive, and highly maintainable architecture suitable for enterprise-scale applications.
Key Takeaways
- ✔ Always use Selectors to read Store data.
- ✔ Use Feature Selectors as the foundation for feature state.
- ✔ Create memoized Selectors with
createSelector(). - ✔ Compute derived state instead of storing duplicate values.
- ✔ Compose Selectors to build reusable business logic.
- ✔ Keep Selectors pure and free of side effects.
- ✔ Convert Selector Observables to Signals for modern Angular templates.
- ✔ Organize Selectors by feature module.
- ✔ Combine Selectors with OnPush Change Detection for optimal performance.
- ✔ Selectors are one of the most frequently discussed NgRx interview topics.
Next Article
➡️ 100-NgRx-Entity-QA.md