Skip to content Skip to sidebar Skip to footer

Ngrx Selector Typeerror Cannot Read Property Map of Undefined

When using NgRx to build our application, one of the first things that we have to practice is to decide what is the best possible format for storing data inside the store.

Handling the business concern information in our centralized store is something that we will need to practise in any NgRx application, but the process can be repetitive and time-consuming if we have to come up with our own advertising-hoc solution.

We frequently notice ourselves handwriting the verbal same reducer logic and selectors for unlike types of data, which is mistake decumbent and slows downwardly the evolution process.

In this post, we are going to learn how NgRx Entity really helps us to handle the business data in our store.

Nosotros are going to empathize in detail what is the value proposition of NgRx Entity and of the Entity State format that it uses, nosotros volition acquire exactly what problem NgRx Entity solves and know when to utilise it and why.

Table of Contents

In this post, we will cover the post-obit topics:

  • What is an Entity?
  • How to store collections of entities in a store?
  • designing the entity store land: Arrays or Maps?
  • What is NgRx Entity, when to use it?
  • The NgRx Entity Adapter
  • Defining the default entity sort society
  • Defining the Entity initial state
  • Write simpler reducers with NgRx Entity
  • Using NgRx Entity Selectors
  • What NgRx Entity is not designed to do
  • Configuring a custom unique ID field
  • Scaffolding an Entity using NgRx Schematics
  • The NgRx Entity Update<T> type
  • Github repo with running example
  • Conclusions

Note that this postal service builds on other store concepts such as actions, reducers and selectors. If you are looking for an introduction to NgRx Store and to the store architecture in general, take a look at this post:

Angular Service Layers: Redux, RxJs and Ngrx Store - When to Utilise a Store And Why?.

If you are looking for a guide to assist setup the NgRx development environment, including DevTools, the time travelling debugger with router integration and NgRx Shop Freeze, have a look at:

Angular Ngrx DevTools: Of import Practical Tips.

So without further ado, permit's go started in our NgRx Entity deep swoop! Let's start at the beginning and kickoff by understanding commencement what is an entity.

What is an Entity?

In NgRx, nosotros store different types of state in the store, and this typically includes:

  • business organisation data, such equally for example Courses or Lessons, in the case of an online course platform

  • some UI state, such as for instance UI user preferences

An Entity represents some sort of business organization data, and so Grade and Lesson are examples of entity types.

In our code, an entity is divers as a Typescript type definition. For example, in an online course organization, the most important entities would be Grade and Lesson, divers with these 2 custom object types:

The Entity unique identifier

As we can see, both entities have a unique identifier field chosen id, which can be either a string or a number. This is a technical identifier that is unique to a given instance of the entity: for example, no two courses have the same id.

Most of the data that nosotros store in the shop are entities!

How to store collections of entities in a shop?

Let's say that for example, nosotros would like to store a collection of courses in the in-memory store: how would we practise that? One manner would be to shop the courses in an array, under a courses property.

The complete store state would so expect something like this:

Storing entities in the store in the form of an array is the first thing that comes to mind, but that approach can crusade several potential problems:

  • if we want to expect up a course based on it'south known id, we would have to loop through the whole collection, which could be inefficient for very big collections

  • more than that, by using an array we could accidentally shop different versions of the same course (with the same id) in the assortment

  • if nosotros store all our entities as arrays, our reducers will look near the aforementioned for every entity

  • For example, take the simple instance of adding a new entity to the drove. We would be reimplementing several times the exact same logic for adding a new entity to the collection and reordering the assortment in guild to obtain a certain custom sort order

As nosotros tin can see, the format nether which nosotros store our entities in the shop has a big touch on on our program.

Let'due south then try to find out what would exist the ideal format for storing entities in the store.

Designing the entity store state: Arrays or Maps?

One of the roles of the store is to act as an in-retentiveness client-side database that contains a slice of the whole database, from which we derive our view models on the client side via selectors.

This works equally opposed to the more traditional design that consists in bringing the view model from the server via API calls. Considering the store is an in-memory database, it would make sense to store the concern entities in their ain in-retentiveness database "table", and give them a unique identifier similar to a primary primal.

The data can then be flattened out, and linked together using the entity unique identifiers, simply similar in a database.

A good way of modeling that is to store the entity collection under the grade of a Javascript object, which works but like a Map. In this setup, the cardinal of the entity would be the unique id, and the value would be the whole object.

In that new format, this is what the whole store country would look like:

Designing the state for id lookups

As we can run across, this format makes information technology actually elementary to lookup entities by id, which is a very common operation. For example, in club to lookup the form with an id of ane, we would but have to write:

          state.courses[1]                  

Information technology also flattens out the state, making it simpler to combine the multiple entities and 'join' them via a selector query. But at that place is but one problem: we have lost the information virtually the gild of the drove!

This is because the properties of a Javascript object have no club associated to them, unlike arrays. Is there are any to still shop our data by id in a map, and still preserve the data near the order?

Designing the state for preserving entity order

Yep there is, we just have to use both a Map and an Array! Nosotros store the objects in a map (called entities), and nosotros store the order information in an array (chosen ids):

The Entity State format

This country format, which combines a map of entities with an array of ids is known every bit the Entity State format.

This is the ideal format for storing business organization entities in a centralized store, but maintaining this land would represent an extra brunt while writing our reducers and selectors, if we would have to write them manually from scratch.

For example, if nosotros would accept to write some blazon definitions to correspond the consummate shop state, they would look something like this:

Every bit we tin see, we already accept here some repetition going on, equally the types CoursesState and LessonsState are near identical. More than that, all the reducer and selector lawmaking for these two entities would be very similar as well.

Writing reducers that support the Entity State format

Take for example a reducer for a LoadCourse activeness, that takes the current CoursesState and adds a new course to it and reorders the collection based on the seqNo field.

This is what the reducer logic for the LoadCourse activity would look like:

Every bit we can run across, it's quite some code for but adding a course to the shop. The problem is that nosotros would have to write similar code for other common operations such equally updating a course in the shop or deleting it.

Avoiding repeated reducer logic

But a bigger trouble than that is that the lawmaking for an equivalent LoadLesson action, that loads i single Lesson into LessonsState would be about identical:

Except for using the type Lesson instead of Course, this code is practically identical to the reducer logic that nosotros wrote before!

Every bit we can see, keeping our entities in this dual array and map scenario gives ascent to a lot of repetitive lawmaking.

Avoiding repeated Selector logic

More the repeated type definitions, the repeated initial land, and almost identical reducer logic, we would besides have a lot of nearly identical selector logic.

For case, here is some usually needed selector for the Course entity, that selects all courses available in the store:

Quick explanation on feature selectors

Notice the selectCoursesState feature selector, this is an auxiliary selector that simply takes the property courses of the whole store state, like this:

          storeState["courses"]                  

The advantage of using this utility is that this is type safety, and makes it elementary to ascertain lazy loaded selectors, that don't take access to the type definition of the root store state.

The selector selectAllCourses gets all the courses in the store and puts them in an array, and sorts the array according to the seqNo field.

The problem is that nosotros would demand some nearly identical logic for the Lesson entity:

As we can run across, this code is almost identical to the selector that we wrote before for the Form entity.

It's a lot of repeated code

Allow's summarize what type of code we have seen and then far that is almost identical:

  • entity land definitions (like CoursesState and LessonsState)
  • initial reducer state (like initialCoursesState and initialLessonsState)
  • reducer logic
  • selector logic

This is a lot of repeated code only to proceed the data in our database in this optimized Entity State format. The problem is, that this is the ideal format for storing related entities in the store, and if we don't use it we will probable end up running into other issues.

The good news is that nosotros tin can avoid about all this repeated code by leveraging NgRx Entity!

What is NgRx Entity, when to use it?

NgRx Entity is a small library that helps us to keep our entities in this ideal Entity state format (array of ids plus map of entities).

This library is designed to be used in conjunction with NgRx Store and is actually a key part of the NgRx ecosystem. It's just and so much better to apply NgRx Entity from the starting time in our project instead of trying to come with our own advertising hoc in-memory database format.

Let'south at present acquire the many ways that NgRx Entity helps us to write our NgRx application.

Defining the Entity State

Going back to our Course entity, permit's now redefine the entity state using NgRx Entity:

This is identical to the blazon definition we wrote earlier, simply we now don't accept to define the ids and entities property for each separate entity. Instead, we can simply inherit from EntityState and accept the same upshot with the aforementioned type rubber and much less code.

The NgRx Entity Adapter

In order to exist able to use the other features of NgRx Entity, we need to kickoff create an entity adapter. The adapter is a utility class that provides a serial of utility functions that are designed to get in really unproblematic to manipulate the entity land.

The adapter is what is going to allow us to write all our initial entity country, reducers and selectors in a much simpler manner, while however keeping our entity in the standard EntityState format.

Here is the adapter for the Form entity, configured to sort our entities using the seqNo field:

Defining the default entity sort club

Observe hither that we have used the optional sortComparer property, that is used to set the sorting order of the Grade entity, which is what is going to determine the social club of the ids array for this entity.

If nosotros don't use this optional belongings, and so the id field is going to exist used to sort the courses.

Write simpler reducers with the NgRx Entity Adapter

Permit's now accept the adapter and utilize it to define the initial state that we will need for our reducers.

We will then implement the same reducer logic as before:

Notice how much easier it is now to write our reducer logic using the adapter. The adapter is going to helps us to manipulate the existing CourseState, past doing in the addOne call everything that we were doing before manually:

  • addOne volition create a copy of the existing state object, instead of mutating the existing state
  • so addOne is going to create a re-create of the ids array and it volition add the new grade in the correct sort position
  • a copy of the entities object is going to be created, that points to all previous courses objects, without recreating those objects via a deep copy
  • the new entities object will take the new grade added

Benefits of using the entity adapter

As we can come across, past using the adapter to write our reducers, we tin spare a lot of piece of work and avert common reducer logic bugs, as this type of logic is easy to get wrong.

It's not uncommon to accidentally mutate the store land, which might crusade problems especially if nosotros are using OnPush change detection in our awarding.

Using the adapter prevents all those bug, while reducing a lot the amount of code needed to write our reducers.

Operations supported by the NgRxEntity Adapter

Too addOne, the NgRx Entity Adapter supports a whole series of common collection modification operations, that we would otherwise have to implement ourselves by manus.

Hither is a complete set of examples for all the supported operations:

The adapter methods behave in the following way:

  • addOne: add i entity to the collection
  • addMany: add several entities
  • addAll: replaces the whole collection with a new one
  • removeOne: remove one entity
  • removeMany: removes several entities
  • removeAll: clear the whole collection
  • updateOne: Update one existing entity
  • updateMany: Update multiple existing entities
  • upsertOne: Update or Insert i entity
  • upsertMany: Update or Insert multiple entities

Now imagine what it would exist if we would have to implement all this reducer logic ourselves!

Using NgRx Entity Selectors

Another thing that NgRx entity helps usa with is with normally needed selectors, such as selectAllCourses and selectAllLessons.

By running the post-obit command, nosotros have available a whole series of commonly needed selectors, generated on the fly:

These selectors are all ready to be used direct in our components or as the starting point for building other selectors.

Discover that these selectors are all named the aforementioned way independently of the entity, so if you lot demand several in the same file, its recommended to import them in the following way:

These selectors are ready to be used and are simply equally type rubber as the ones that we wrote manually ourselves.

What NgRx Entity is not meant to do

Observe that although NgRx Entity made information technology much easier to write the state, reducer and selector logic of the Grade entity, we still had to write the reducer office itself, although this fourth dimension effectually in a simpler style using the adapter.

Using NgRx Entity does not avoid having to write reducer logic for each entity, although it makes it much simpler.

This means that for the Lesson entity we would have to do something very similar. The convention is to put all this closely related code that uses the adapter directly in the same file where our entity reducer part is defined.

In the case of the Lesson entity, this is what the complete lesson.reducers.ts file would look like:

In practice, each entity has slightly different reducer logic so at that place will exist no lawmaking repetition between reducer functions.

If you lot are looking for a solution that takes this one step further and removes the need to write entity specific reducer logic, have a look at ngrx-data.

Configuring a custom Unique ID field

Equally we have mentioned, the entities in our plan should all accept a technical identifier field called id. But if by some reason this field is either:

  • not available in a given entity
  • or it has a different name
  • or we simply would prefer to apply another property which happens to be a natural primal

We can however do that by providing a custom id selector function to the adapter. Here is an example:

This role will be called by the adapter to excerpt a unique key from a given entity.

In this example, we are creating a unique identifier for the Lesson entity by concatenating the courseIdbelongings with the lesson sequential number, which is unique for a given grade.

Treatment custom state backdrop

And so far nosotros accept been defining our entity state only by extending the EntityState type. But its possible that our entity state also has other custom properties other than the standard ids and entities.

Let'due south say that for the Grade entity, we besides need an extra flag which indicates if the courses take already been loaded or not. We could define that extra state property in CoursesState, and so update that holding in our reducer logic using the adapter.

Here is a complete example of the CoursesState reducer file courses.reducers.ts, now including the actress state property:

Here is what we had to exercise to include this actress belongings:

  • first we have added the allCoursesLoaded property to the type definition of CoursesState
  • next, nosotros need to ascertain the initial value of this holding in initialCoursesState, by passing an optional object to the call to getInitialState()
  • we now can set this property in our reducer logic, similar we are doing here in the ALL_COURSES_LOADED reducer.
  • in order to so, we uncomplicated need to make a copy of the CourseState using the spread (... operator), and then we modify the holding and we pass this new state object to the adapter call

Scaffolding an Entity using NgRx Schematics

If y'all would similar to quickly generate a reducer file like the ones we accept shown in this post, you can go a very skillful starting betoken by using NgRx Schematics.

The start affair we need to do in society to utilise entity schematics is to gear up this CLI property:

          ng config cli.defaultCollection @ngrx/schematics                  

Later this, we can now generate a completely new Lesson reducer file by running the following command:

          ng generate entity --name Lesson --module courses/courses.module.ts                  

What does NgRx Entity Schematics generate?

Allow's now inspect the output generated by the control in a higher place. Commencement, we have an empty Entity model file:

This schematic command will also generate a consummate action file, with each activeness corresponding to one state modification method in the entity adapter:

Reviewing the content of the Actions file

This file follows the normal recommended structure of an action file:

  • 1 enum LessonActionTypes with one entry per Lesson action
  • one class per action, with the data passed to the activity via a payload property
  • one union blazon LessonActions at the bottom, with all the action classes of this file

This last union type is especially helpful for writing reducer logic. Thanks to it, we can have full blazon inference and IDE auto-completion inside the instance blocks of our reducers.

The NgRx Entity Update type

Discover also that in the definition of some actions we are using the type Update<Lesson>. This is an auxiliary blazon provided past NgRx Entity to help model partial entity updates.

This type has a property id that identifies the updated entity, and another property called changesthat specifies what modifications are being made to the entity.

Here is an example of valid update object for the Course type:

Reviewing the content of the reducers file

The NgRx Entity schematic command will also generate the Entity reducer file plus a exam, as expected. Here is the content of the reducer file:

How to best utilize the schematics output?

Notice that the generated schematics files (like whatsoever other file generated the CLI)
are not meant to remain unchanged.

In fact, you might not even desire to use the actions file for example, only instead write your ain deportment with a given set of conventions similar the ones recommended in this talk:

Also, probably non all actions are going to be needed in the awarding, then it'south important to keep simply the ones that we need and adapt them. As usual, the files that are generated by schematics are merely a helping starting indicate that needs to exist adjusted on a case past instance basis.

Github repo with running example

For a complete running example of a small application that shows how to use NgRx Entity with the two entities that we have used in the examples (Course and Lesson), have a look at this repository.

Here are the NgRx DevTools showing the shop content with the two entities:

the Ngrx DevTools in action

Conclusions

NgRx Entity is an extremely useful package, but in guild to understand it its essential to first exist familiar first with the base shop concepts like Actions, Reducers and Selectors, and with the store architecture in general.

If we are already familiar with these concepts, we probably already tried to find the best way to structure the data within our store.

NgRx Entity provides an reply for that past proposing the Entity State format for our business entities, which is optimized for lookups by id while notwithstanding keeping the entity gild information.

The NgRx Entity Adapter together with NgRx Schematics makes information technology very uncomplicated to get started using NgRx Entity to store our information.

But discover that not all store land needs to utilise NgRx Entity!

NgRx Entity is specifically designed to handle just the business entities in our store, making information technology simple to shop them in memory in a convenient way.

Larn more virtually the NgRx Ecosystem

I hope that this mail service helps with getting started with Ngrx Entity, and that you enjoyed information technology!

If y'all would like to learn a lot more than nearly NgRx, we recommend checking the NgRx with NgRx Data - The Complete Guide video course, where nosotros will encompass the whole NgRx ecosystem in much more detail.

If you are looking to acquire how to get started with the NgRx ecosystem, you might want to cheque the previous blog posts of this series:

  • Angular Service Layers: Redux, RxJs and Ngrx Store - When to Apply a Store And Why?
  • Angular Ngrx DevTools: Important Practical Tips

As well, if y'all have some questions or comments please permit me know in the comments below and I volition get back to you.

To get notified of upcoming posts on Ngrx and other Angular topics, I invite yous to subscribe to our newsletter:

If you are simply getting started learning Athwart, have a look at the Angular for Beginners Course:

sweeneybehatee76.blogspot.com

Source: https://blog.angular-university.io/ngrx-entity/

Mag-post ng isang Komento for "Ngrx Selector Typeerror Cannot Read Property Map of Undefined"