Using EntityAdapter with ComponentStore: @ngrx/entity Series – Part 3

As someone who enjoys the ComponentStore on an average level, I have written simple reactive CRUD logic several times. While storing a vast number of entities in the component state might not be a frequent use case, I will briefly illustrate the usage of the EntityAdapter with the @ngrx/component-store.

In this article:

YB_300x300
Yannick Baron is architecture consultant at Thinktecture and focuses on Angular and RxJS.

This is the third article of the series about @ngrx/entity.

  1. Managing Your Collections With EntityAdapter
  2. Multiple Entity Collections in the Same Feature State
  3. Using EntityAdapter With ComponentStore

Headsup

If you have followed the series, you should be familiar with the EntityState interface. It describes how the EntityAdapter expects our collection to be stored. In the previous articles, we elaborated in detail on how to handle single and multiple collections.
For this example, we simply make EntityState the state of our component and extend it with a couple of common properties. But everything shown before, when we need to handle multiple entity types, applies here as well!

Basic Setup

We start out by simply defining our component state interface, which will contain a single collection and some properties. We do this by extending EntityState:
				
					interface PersonComponentState extends EntityState<Person> {
  loading: boolean;
  error?: string;
}
				
			
Creating the EntityAdapter and the initial state can be done as before, and the ComponentStore goes along with it:
				
					const personAdapter = createEntityAdapter<Person>();

const initialState = personAdapter.getInitialState({ loading: true });

@Injectable()
class PersonComponentStore extends ComponentStore<PersonComponentState> {
  constructor() {
    super(initialState);
  }
}
				
			

Selector and Updater Bliss

Using the EntityAdapter, we can now easily manage our collection as we have seen before in our reducer functions, which will now simply become updaters:
				
					class PersonComponentStore extends ComponentStore<PersonComponentState> {
  // ...

  readonly addPerson = this.updater((state, person: Person) => {
    return personAdapter.addOne(person, state);
  });

  readonly updatePerson = this.updater((state, update: Update<Person>) => {
    return personAdapter.updateOne(update, state);
  });

  // ...
}
				
			
For selectors, we need to extract them from the EntityAdapter first:
				
					// ...

const { selectAll } = personAdapter.getSelectors();

class PersonComponentStore extends ComponentStore<PersonComponentState> {
  readonly persons$ = this.select(state => selectAll(state));

  // ...
}
				
			

Conclusion

In this series, I have shown, that using the @ngrx/entity package is quite simple and often beneficial. The way this abstraction is implemented allows us to make use of the EntityAdapter in various ways.
 
As this is the last part of this series, it is kept very brief. Please refer to the other parts for a detailed dive into how EntityAdapter works!
 
I hope I could inspire you to make use of the entity package!
Free
Newsletter

Current articles, screencasts and interviews by our experts

Don’t miss any content on Angular, .NET Core, Blazor, Azure, and Kubernetes and sign up for our free monthly dev newsletter.

EN Newsletter Anmeldung (#7)
Related Articles
.NET
pg
While basic value objects solve primitive obsession, complex domain requirements need sophisticated modeling techniques. This article explores advanced patterns using Thinktecture.Runtime.Extensions to tackle real-world scenarios: open-ended dates for employment contracts, composite file identifiers across storage systems, recurring anniversaries without year components, and geographical jurisdictions using discriminated unions.
19.10.2025
.NET
pg
Domain models often involve concepts that exist in multiple distinct states or variations. Traditional approaches using enums and nullable properties can lead to invalid states and scattered logic. This article explores how discriminated unions provide a structured, type-safe way to model domain variants in .NET, aligning perfectly with Domain-Driven Design principles while enforcing invariants at the type level.
06.10.2025
.NET
pg
Learn how to seamlessly integrate Smart Enums with essential .NET frameworks and libraries. This article covers practical solutions for JSON serialization, ASP.NET Core model binding for both Minimal APIs and MVC controllers, and Entity Framework Core persistence using value converters. Discover how Thinktecture.Runtime.Extensions provides dedicated packages to eliminate integration friction and maintain type safety across your application stack.
21.09.2025