Announcing NgRx Version 10: New packages for local component state and reactive components, swag store, and more!

Brandon Roberts
@ngrx
Published in
8 min readAug 10, 2020

Today we’re happy to announce the version 10 release of the NgRx platform. This release contains new features, bug fixes, and some breaking changes, all aimed at improving the developer experience when using NgRx libraries.

NgRx Conf Update⏲️

In the version 9 release announcement, we also announced NgRx Conf, a celebration of all things Reactive Angular. As with many other conferences this year, we had to make some adjustments, and will not have an in-person conference this year. We are continuing to work with our vendors and partners to move the conference to a tentative date of May 20th-21st, 2021. We will provide more details about planned activities for 2020.

Follow @NgRxConf for future updates!

NgRx Conf’s Premier Sponsor

We also welcome Nrwl as our premier sponsor for NgRx Conf! Nrwl has been a longtime promoter of NgRx as a tool when building large applications in Angular, and we couldn’t be more excited to have them partner with us for NgRx Conf.

With Nrwl, you’ll find a consulting firm that truly enables you to get a deeper understanding and navigate the most nuanced challenges of building software with Angular, React, and other modern Javascript frameworks.

Comprised of former Angular team members, Googlers, and renowned experts, when working with us, you’ll build software better and faster. You can leverage our consulting, training, and engineering, plus open-source tools like Nx to elevate your enterprise’s development practice.

New ComponentStore package for local state management

NgRx Store is about managing complex state from many different sources at a global application level. In some cases, you still want to manage state in a consistent way locally, and don’t need the indirection of actions, reducers, and effects. We’ve designed a new package to handle state at a local level while providing the same benefits similar to the NgRx Store. Check out the comparison between them in our documentation.

ComponentStore is a stand-alone library that helps to manage local/component state. It’s an alternative to reactive push-based “Service with a Subject” approach.

Key Concepts

  • Local state is typically tied to the life-cycle of a particular component, and is cleaned up when that component is destroyed
  • Local state can be updated through a setState method. An update can also be defined using an updater method imperatively or with an observable. No indirection from actions is required.
  • Local state can be read through observable state$ property, and by a defined selector using the select method. The select method can also be used for the composition of data from multiple sources, such as other selectors, global store or any other observables.
  • Side effects can be triggered through an effect method, imperatively or with an observable.

To install the package, use the ng add command:

ng add @ngrx/component-store

To define a local store, extend the ComponentStore class with the shape of your local state:

export interface MoviesState {
movies: Movie[];
}
@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {

constructor() {
super({movies: []});
}
}

To read data, use the select method:

@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {

constructor() {
super({movies:[]});
}

readonly movies$: Observable<Movie[]> = this.select(
state => state.movies);
}

To update the store, define an updater:

@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {

constructor() {
super({movies: []});
}
readonly movies$: Observable<Movie[]> = this.select(
state => state.movies);
readonly addMovies = this.updater((state, movie: Movie[]) => ({
movies: [...state.movies, ...movies],
}));
}

To define a side-effect, use the effect method.

@Injectable()
export class MoviesStore extends ComponentStore<MoviesState> {

constructor(private readonly moviesService: MoviesService) {
super({movies: []});
}
readonly movies$: Observable<Movie[]> = this.select(
state => state.movies);
readonly addMovies = this.updater((state, movie: Movie[]) => ({
movies: [...state.movies, ...movies],
}));
readonly getMovies = this.effect(() => {
return this.moviesService.fetchMovies().pipe(
tap({
next: (movie) => this.addMovies(movies),
error: (e) => this.logError(e),
}),
catchError(() => EMPTY),
))
);
})
}

To use the local store, add it to your component providers, and use the store to manage state:

@Component({
template: `
<div *ngFor="let movie of movies$ | async">
{{ movie.name }}
</div>
`,
providers: [MoviesStore],
})
export class MoviesPageComponent implements OnInit {
movies$ = this.moviesStore.movies$;
constructor(private readonly moviesStore: MoviesStore) {}

ngOnInit() {
this.moviesStore.getMovies();
}
}

Read more about using ComponentStore in our documentation.

NgRx ComponentStore gives you the ability to manage local state and side effects without manual subscriptions, and easy integration with any global state management solution. Thanks to Kevin Elko for the original implementation, and to all the community for contributing feedback for this new package!

New Component package for more reactive components (Experimental)

As we move forward in this new world with Ivy, we want to rethink how we handle reactivity in Angular Zoneless applications. The async pipe set a standard for Angular applications for handling observables and promises in the template. NgRx Component goes further to help you build fully reactive applications with helpers for rendering using observables in the template.

Key Concepts

  • Providing a better way to handle observables in the template
  • Providing smarter handling of change detection for performance-sensitive UIs.

To install the package, use the ng add command:

ng add @ngrx/component

To use the pipe or directive, add the ReactiveComponentModule to your NgModule’s imports:

import { ReactiveComponentModule } from '@ngrx/component';
@NgModule({
imports: [
// ... other imports
ReactiveComponentModule
]
})
export class MyFeatureModule {}

NgRx Component includes a pipe and a structural directive as helpers for your template.

*ngrxLet structural directive

The *ngrxLet directive serves as a convenient way of binding observables to a view context (a DOM element scope). It also helps with several internal processing under the hood. If you’re familiar with using the async pipe for reassignment, you’ve probably done this with the *ngIf directive:

<ng-container *ngIf="observableNumber$ | async as n">
<app-number [number]="n">
</app-number>
<app-number-special [number]="n">
</app-number-special>
</ng-container>

The *ngrxLet directive allows you to safely work with observables in the template without extra destroying and recreating DOM elements.

<ng-container *ngrxLet="observableNumber$ as n">
<app-number [number]="n">
</app-number>
</ng-container>
<ng-container *ngrxLet="observableNumber$; let n">
<app-number [number]="n">
</app-number>
</ng-container>

ngrxPush pipe

The ngrxPush pipe serves as a drop-in replacement for the async pipe. It contains intelligent handling of change detection without any changes to the code.

{{observable$ | ngrxPush}}<ng-container *ngIf="observable$ | ngrxPush as o">{{o}}</ng-container><component [value]="observable$ | ngrxPush"></component>

The ngrxPush pipe schedules change detection, allowing your more efficient control over rendering when new values are emitted.

Read more about component in our documentation.

NgRx Component puts us on a path for looking at new ways to build reactive Angular applications. It’s still considered experimental in the v10 release, but we are interested to hear your feedback on how to improve the experience for Angular developers. Thanks to Michael Hladky for the original implementation, and to all the community for contributing feedback for this new package!

New swag store and Discord Server!

By popular request, you can now get official NgRx swag through our store! T-shirts with the NgRx logo are available in many different sizes, materials, and colors. We will look at adding new items to the store such as stickers, magnets, and more in the future. Visit our store to get your NgRx swag today!

We’ve also added a discord server for those who want to engage with other members of the NgRx community, old and new. You can sign up for an account here. We also still have a large community of users on the gitter channel as well that provide continued help and support to our users.

Breaking Changes

This release contains breaking changes. For most of these breaking changes we’ve provided a migration that automatically runs when you upgrade your application with the Angular CLI command mentioned above.

Take a look at the version 10 migration guide for complete information regarding migrating to the latest release. The complete CHANGELOG can be found on our GitHub page.

Upgrading to NgRx 10

To start using NgRx 10, make sure to have the following minimum versions installed:

  • Angular version 10.x
  • Angular CLI version 10.0.1
  • TypeScript version 3.9.x
  • RxJS version 6.5.x

NgRx supports using the Angular CLI ng update command to update your NgRx packages. To update your packages to the latest version, run the command:

ng update @ngrx/store

Contributing to NgRx

We’re always trying to improve the docs and keep them up-to-date. To help us, you can start contributing to NgRx. If you’re unsure where to start, come take a look at our new contribution guide and watch the introduction video Jan-Niklas Wortmann and Brandon Roberts have made to help you get started.

Thanks to all our contributors

NgRx continues to be a community-driven project. Design, development, documentation, and testing all are done with the help of the community. We would like to thank the contributors that helped to work towards this release of NgRx: Michael Hladky, AdditionAddict, Jordan Powell, Keenan Johnson, Lance Finney, Lars Gyrup Brink Nielsen, Miroslav Jonas, Alan Donohoe, Ben Lesh, Brian Love, Christine Legge, Christoph Guttandin, Dillon Fearns, Emily Lam, Evgeny Fedorenko, Felix Lemke, Joshua Keel, Juan Herrera, Kevin Schuchard, Leon Marzahn, Maksym Kobieliev, Michael-James, Santosh Yadav, TheParad0X, Tobias Engelhardt, Wataru KASAHARA, aszechlicki, m00zi, ptouchton, treebeardcpu.

If you are interested in contributing, visit our GitHub page and look through our open issues, some marked specifically for new contributors.

We would also like to give a big thanks to our silver sponsor, BrieBug. BrieBug is one of the top web and mobile application development consulting firms in the state of Colorado. BrieBug provides enterprise Angular consulting, architectural reviews, team training, and staff augmentation, with multiple Angular GDEs on staff. BrieBug was previously a bronze-level sponsor, but has since increased their sponsorship of NgRx development, providing further support for development, travel, and hosting expenses.

Sponsor NgRx

NgRx requires significant time and effort that often goes unpaid, and we would like to change that. If you or your company wants to sponsor continued development of NgRx, please visit our OpenCollective page for different contribution options, buy some swag from our swag store, or contact us directly for other sponsorship opportunities.

Follow us on Medium and on Twitter for the latest updates about the NgRx platform.

More about NgRx Conf Sponsor — Nrwl and Nx:

  • Visit Nx.dev to get Nrwl.io’s open-source toolkit for monorepo development.
  • Visit Nx.app, to request access to Nx Cloud, and speed up your build-times by up to 90%! Take advantage of the free-tier to see the benefits.
  • Visit NxPlaybook.com for free and paid Nx courses!

--

--

Brandon Roberts
@ngrx
Editor for

Web dev, tech writer, DevRel at Nrwl, NgRx maintainer, GDE, sports fan, recovering gadget addict, and still learning. Gif game 💪🏿