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
Traditional C# pattern matching with switch statements and if/else chains is error-prone and doesn't guarantee exhaustive handling of all cases. When you add new types or states, it's easy to miss updating conditional logic, leading to runtime bugs. The library Thinktecture.Runtime.Extensions solves this with built-in Switch and Map methods for discriminated unions that enforce compile-time exhaustiveness checking.
26.08.2025
.NET
pg
Value Objects in .NET provide a structured way to improve consistency and maintainability in domain modeling. This article examines their integration with popular frameworks and libraries, highlighting best practices for seamless implementation. From working with Entity Framework to leveraging their advantages in ASP.NET, we explore how Value Objects can be effectively incorporated into various architectures. By understanding their role in framework integration, developers can optimize data handling and enhance code clarity without unnecessary complexity.
12.08.2025
.NET
pg
This article builds upon the introduction of Smart Enums by exploring their powerful capability to encapsulate behavior, a significant limitation of traditional C# enums. We delve into how Thinktecture.Runtime.Extensions enables embedding domain-specific logic directly within Smart Enum definitions. This co-location of data and behavior promotes more cohesive, object-oriented, and maintainable code, moving beyond scattered switch statements and extension methods. Discover techniques to make your enumerations truly "smart" by integrating behavior directly where it belongs.
29.07.2025