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
A key aspect of adopting any new pattern is understanding how it interacts with the surrounding application infrastructure. When using Discriminated Unions, questions arise: How can a Result union be serialized to JSON? How can an OrderState union be persisted using Entity Framework Core? This article explores practical integration strategies with common .NET frameworks.
02.11.2025
.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