Back to the homepage
NgRx

@ngrx/component

In one of the last posts on our blog (NgRx – not only store) we described libraries offered by NgRx. Among them there were many well-known items, but there were also some new ones. One of them is @ngrx/component – a library providing tools to support the implementation of reactive components. In this article we will devote some more attention to it and you will learn what its current components – the *ngrxLet directive and the ngrxPush pipe – offer. We will also answer a very important question if we should use them in production. So, let’s get started!

Installation

To install the library just run the command in a terminal:

npm install @ngrx/component

or

ng add @ngrx/component@latest

Both mentioned library elements are exported by ReactiveComponentModule, which has to be imported in our application module and we are good to go.

ngrxPush

NgrxPush also known as pushPipe is the equivalent of the well-known AsyncPipe. Using ngrxPush in a component looks almost identical:

Look at the example application using async in one component and ngrxPush in the other. The code of the components is identical, they differ only on the template level:

 

 

At first glance, the two pipes mentioned above work almost identically. So where does the difference lie? It turns out that ngrxPush brings corrections on the level of change detection control.

In a standard application written in Angular, both pipes work as follows: when a new value appears in the data stream, they update the value of the variable passed to the view and use the markForCheck method to inform the change detection system that the view needs to be re-rendered. However, using the markForCheck method by itself will not trigger the change detection mechanism and re-render the component, it will only mark the component and all its ancestors as to be checked. So how do we nevertheless get the expected result where new data is rendered? The NgZone is responsible for it. It completes the mechanism mentioned above and it is thanks to it that our new data appears in the view.

ngrxPush and Zoneless mode

In an ideal scenario, the view should respond to the change of data values itself, without support from NgZone or the need  for manually invoking change detection. There are also classes of applications whose developers may simply not want to use the NgZone, e.g. for performance reasons. There are also a number of other potential reasons, but this is a separate issue, beyond the topic of this article.

So what happens when we disable zone in our application? Let’s check by following the instructions in the documentation: https://angular.io/guide/zone#noopzone

 

As you can see, as expected, the component using asyncPipe stopped refreshing the values of the stream in the view. On the other hand, the other component, that uses ngrxPush, continues to work properly despite the lack of NgZone. This is because this pipe, in the absence of the zone, uses the detectChanges method, which is responsible for directly starting the change detection mechanism.

Does this solution have any disadvantages? Unfortunately, yes. If we directly use the same Observable in a view in several places with ngrxPush, change detection will be called as many times as there are these uses. Although this is usually a very fast process, this behavior is a pretty big downside. Can we prevent this somehow? The answer is “yes” again and it is not about using *ngIf. The second hero of today’s article – *ngrxLet – will help us with this.

*ngrxLet

Before we move on to the *ngrxLet directive itself, please answer one question: how many times have you encountered code that uses *ngIf in a similar way?

Many times, I bet, and in fact there is nothing surprising about it. Angular does not provide any alternative to help in such cases, and developers naturally look for a simple replacement solution. Unfortunately, it has a significant downside when it comes to such usage. In case of receiving some falsy value in the stream, the element marked with this directive is removed from the DOM tree. In this context, this is often an undesirable effect.

This is where *ngrxLet can come to our aid – what primarily distinguishes this directive from *ngIf is:

– the element always remains in the DOM tree, regardless of the value received from the data stream,

– this directive does not need any additional use of asyncPipe or ngrxPush to “unpack” the data from the stream, so we can pass Observable directly to it.

Additionally *ngrxLet supports other stream events, which means we can easily handle errors or the end of emissions. As with ngrxPush here we also have the ability to work in a Zoneless environment.

Below is our example application where the ngrxPush repetitions are eliminated in favor of *ngrxLet. In the second component we have async and *ngIf for comparison, which hides the whole ul elements when the initial value in the stream is null:

 

 

Should you use it in production?

At this point, it’s worth noting that until recently the library relied on some change detection features (https://github.com/ngrx/platform/blob/9.2.0/modules/component/src/core/cd-aware/get-change-detection-handling.ts#L4-L5) that came with Ivy and which are not part of Angular’s public API. Probably mainly because of that, initially it used to be possible to download it from the NgRx repository on Github only. Starting with version 10, the maintainers decided to use the API of the existing ChangeDetector instead and make the library available in the npm registry.

However, by visiting the @ngrx/component documentation we can immediately see the following information:

This package is still experimental and may change during development.

Due to this fact, I decided to explore this topic a bit more. Unfortunately, it turns out that the issue containing the roadmap for the library (https://github.com/ngrx/platform/issues/2441) was closed by the main contributor. Following the history of the library on GitHub you can see that a lot of ideas and code were rejected. This was probably the direct reason for the discontinued contribution.

However, wanting to be 100% sure about the status and the future of the library, I asked the source, a member of the NgRx core team, Alex Okrushko. Summarizing the answer, the team gives no guarantee for further development of the library – perhaps in the future it will be withdrawn or even removed. Therefore, Alex encourages you to check it out, but at the same time recommends not to use it in production applications. As a consolation, we can add that Alex also mentioned another, alternative idea of NgRx for Zoneless applications. For now, however, it is at a very early stage, its development is rather low priority and details are not disclosed.

Summary

The @ngrx/component library brings a lot of freshness to the NgRx family by providing completely different tools than what we have been used to, namely those related to state management. Although its future is questionable, it’s still worthwhile to familiarize yourself with its assumptions and the problems it tries to solve. It gives a broader perspective on Angular applications and libraries trends.

About the author

Krzysztof Skorupka

Angular Team Leader at House of Angular. Krzysztof guides team members and helps them develop a senior software engineer skill set, while developing Angular web apps by himself. He is interested in business analysis and architecture of web apps, adapted to client needs.

Don’t miss anything! Subscribe to our newsletter. Stay up-to-date with the latest trends, tips, meetups, courses and be a part of a thriving community. The job market appreciates community members.

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *