Angular Signal Store
Master Angular Signal Store with state management, computed signals, methods, rxMethod, feature composition, enterprise architecture, best practices, and interview questions.
Angular applications traditionally use Services or NgRx Store for state management. With the introduction of Signals, the NgRx team introduced Signal Store, a modern reactive state management solution built on Angular Signals.
Signal Store provides:
- Reactive state using Signals
- Computed state
- Immutable updates
- Feature composition
- Dependency Injection
- RxJS interoperability
- Excellent performance
- Less boilerplate than traditional NgRx Store
Signal Store is ideal for medium and large Angular applications that want the simplicity of Signals while maintaining structured state management.
Table of Contents
- What is Signal Store?
- Why Use Signal Store?
- Signal Store Architecture
- Creating a Signal Store
- State Management
- Computed Signals
- Store Methods
- RxJS Integration
- Feature Composition
- Enterprise Banking Example
- Performance Best Practices
- Common Mistakes
- Top 10 Interview Questions
- Interview Cheat Sheet
- Summary
- Next Article
What is Signal Store?
Signal Store is a modern state management library from the NgRx ecosystem that uses Angular Signals as the foundation for managing application state.
Unlike traditional NgRx Store:
- No Actions
- No Reducers
- No Effects
- No Selectors
Instead, it uses:
- State
- Computed Signals
- Methods
- Reactive Signals
Why Use Signal Store?
Traditional Store requires multiple files.
Actions
↓
Reducers
↓
Effects
↓
Selectors
Signal Store simplifies everything into a single store.
Benefits include:
- Less boilerplate
- Easier learning curve
- Better readability
- Excellent performance
- Built-in Signals
- Modern Angular architecture
Signal Store Architecture
flowchart LR
Component
Component --> SignalStore
SignalStore --> State
State --> Computed
Computed --> UI
Installing Signal Store
npm install @ngrx/signals
Creating a Signal Store
import {
signalStore,
withState
} from '@ngrx/signals';
export const CustomerStore = signalStore(
withState({
customers: [],
loading: false
})
);
This creates a reactive store backed entirely by Signals.
Reading State
State values are Signals.
@Component({...})
export class CustomerComponent {
readonly store = inject(CustomerStore);
}
Template
@for (
customer of store.customers();
track customer.id
) {
<div>
{{ customer.name }}
</div>
}
No Async Pipe is required.
Updating State
Signal Store provides patchState().
patchState(
store,
{
loading: true
}
);
Updating customers
patchState(
store,
{
customers: data
}
);
State Update Flow
flowchart LR
Component
Component --> StoreMethod
StoreMethod --> patchState
patchState --> Signal
Signal --> UI
Computed Signals
Derived state should use computed signals.
import {
withComputed
} from '@ngrx/signals';
export const CustomerStore = signalStore(
withState({
customers: []
}),
withComputed(({ customers }) => ({
customerCount: computed(
() => customers().length
)
}))
);
Usage
store.customerCount()
Computed Architecture
flowchart LR
State
State --> Computed
Computed --> Component
Component --> UI
Store Methods
Business logic belongs inside methods.
import {
withMethods
} from '@ngrx/signals';
export const CustomerStore = signalStore(
withState({
customers: []
}),
withMethods(
(store) => ({
clearCustomers(){
patchState(
store,
{
customers: []
}
);
}
})
)
);
Usage
store.clearCustomers();
RxJS Integration
Signal Store supports RxJS using rxMethod().
loadCustomers = rxMethod<void>(
pipe(
switchMap(() =>
this.customerService.getCustomers()
)
)
);
Useful for:
- HTTP requests
- WebSockets
- Polling
- Streaming data
Signal Store Features
flowchart TD
State
State --> Computed
State --> Methods
Methods --> RxMethod
RxMethod --> API
API --> patchState
Feature Composition
Signal Store allows features to be composed together.
Example
signalStore(
withState(...),
withComputed(...),
withMethods(...)
);
Each feature has a clear responsibility.
Dependency Injection
Signal Stores integrate naturally with Angular Dependency Injection.
readonly customerStore =
inject(CustomerStore);
No manual service wiring is needed.
Enterprise Banking Example
A banking application uses Signal Store for:
- Customer Dashboard
- Account Summary
- Credit Cards
- Investments
- Loans
- Notifications
Architecture
flowchart TD
Dashboard
Dashboard --> CustomerStore
CustomerStore --> Signals
Signals --> Computed
Computed --> Dashboard
Benefits
- Reactive UI
- Less boilerplate
- Better maintainability
- Fast rendering
- Simple architecture
Project Structure
stores/
├── customer.store.ts
├── account.store.ts
├── loan.store.ts
├── investment.store.ts
├── auth.store.ts
└── notification.store.ts
Signal Store vs NgRx Store
| Feature | Signal Store | NgRx Store |
|---|---|---|
| Signals | ✅ Native | Via Selectors |
| Actions | ❌ | ✅ |
| Reducers | ❌ | ✅ |
| Effects | ❌ | ✅ |
| Boilerplate | Very Low | Higher |
| Learning Curve | Easy | Moderate |
| Enterprise Ready | ✅ | ✅ |
Performance Best Practices
| Practice | Benefit |
|---|---|
| Keep stores small | Better maintainability |
| Use computed for derived state | Faster rendering |
| Use patchState() | Immutable updates |
| Keep business logic in methods | Cleaner architecture |
| Use rxMethod() for async work | Better separation of concerns |
| Split stores by feature | Better scalability |
| Avoid unnecessary computed signals | Better performance |
| Use OnPush components | Faster UI updates |
Common Mistakes
Storing Derived Values
❌ Wrong
customerCount: 150
Use computed instead.
Large Stores
Avoid one store managing the entire application.
Split by feature.
Business Logic in Components
Move reusable business logic into store methods.
Mutating State
Never mutate arrays directly.
❌ Wrong
store.customers().push(customer);
Always use patchState().
Ignoring RxJS
For asynchronous operations such as HTTP requests, prefer rxMethod() instead of placing networking logic in components.
Advantages
| Feature | Benefit |
|---|---|
| Signals | Fine-grained reactivity |
| Computed | Derived state |
| Methods | Encapsulated business logic |
| patchState() | Immutable updates |
| RxJS Integration | Async workflows |
| Feature Composition | Modular architecture |
| Angular DI | Seamless integration |
| Less Boilerplate | Faster development |
Top 10 Signal Store Interview Questions
1. What is Signal Store?
Answer
Signal Store is a modern state management solution from the NgRx ecosystem that uses Angular Signals to manage reactive application state with minimal boilerplate.
2. How is Signal Store different from NgRx Store?
Answer
Signal Store eliminates Actions, Reducers, Effects, and Selectors, relying instead on Signals, computed values, and methods while still promoting structured state management.
3. What is withState()?
Answer
withState() defines the reactive state for a Signal Store and creates writable signals for each state property.
4. What is patchState()?
Answer
patchState() updates one or more state properties immutably without replacing the entire state object.
5. What is withComputed()?
Answer
withComputed() defines derived state using Angular's computed() function, ensuring values are automatically recalculated when dependencies change.
6. What is withMethods()?
Answer
withMethods() encapsulates business logic inside the store, making components simpler and improving code reuse.
7. What is rxMethod()?
Answer
rxMethod() integrates RxJS with Signal Store, making it easier to perform asynchronous tasks such as HTTP requests while keeping state updates organized.
8. Can Signal Store work with Dependency Injection?
Answer
Yes. Signal Stores are injectable and integrate seamlessly with Angular's Dependency Injection system using inject().
9. When should Signal Store be used?
Answer
Use Signal Store when building modern Angular applications that benefit from Signals and need structured state management with less boilerplate than traditional NgRx Store.
10. What are Signal Store best practices?
Answer
- Split stores by feature
- Keep stores focused
- Use computed for derived state
- Keep business logic in methods
- Use
patchState()for updates - Use
rxMethod()for asynchronous operations - Avoid mutating state directly
Interview Cheat Sheet
| Requirement | Recommended Solution |
|---|---|
| Reactive State | withState() |
| Derived State | withComputed() |
| Business Logic | withMethods() |
| Async Operations | rxMethod() |
| State Updates | patchState() |
| Dependency Injection | inject() |
| UI Reactivity | Signals |
| Feature Organization | Multiple Stores |
| Performance | OnPush + Signals |
| Enterprise Apps | Signal Store |
Summary
Signal Store is the next generation of state management in the NgRx ecosystem, combining the power of Angular Signals with a lightweight, structured API. By using withState(), withComputed(), withMethods(), and patchState(), developers can build highly reactive applications with significantly less boilerplate than traditional NgRx Store. For asynchronous workflows, rxMethod() bridges RxJS and Signals, making Signal Store an excellent choice for modern enterprise Angular applications.
Key Takeaways
- ✅ Signal Store is built on Angular Signals.
- ✅ It greatly reduces boilerplate compared to traditional NgRx Store.
- ✅
withState()defines reactive state. - ✅
withComputed()creates derived values. - ✅
withMethods()encapsulates business logic. - ✅
patchState()performs immutable updates. - ✅
rxMethod()integrates RxJS for asynchronous operations. - ✅ Organize stores by feature for scalability.
- ✅ Combine Signal Store with OnPush for optimal performance.
- ✅ Signal Store is becoming an increasingly common Angular interview topic.
Next Article
➡️ 102-NgRx-Best-Practices-QA.md