NgRx 5 and Schematics

Brandon Roberts
@ngrx
Published in
4 min readFeb 13, 2018

Today we are announcing the next major release of the NgRx platform of libraries. NgRx version 5 brings fixes, new features and a new library to the platform. While this may sound substantial, there are no substantial breaking changes in this release, other than removal of deprecated code in version 4 and bumping the minimum version of RxJS for pipeable operator support. This should make upgrading to the latest version fairly trivial.

Breaking Changes

The deprecatedtoPayload utility function in @ngrx/effects 4.1 was removed.

New Features

Pipeable operators

The release of RxJS 5.5 introduced support for pipeable operators, providing a better way to only use the operators you need. The Store and Effects libraries provide pipeable versions of the select and ofType operators respectively. The instance version of these operators are still available for backwards compatibility.

Store

import { Store, select } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';

interface AppState {
count: number;
}

@Component({
selector: 'my-app',
template: `
<button (click)="increment()">Increment</button>
<div>Current Count: {{ count$ | async }}</div>
<button (click)="decrement()">Decrement</button>

<button (click)="reset()">Reset Counter</button>
`
})
export class MyAppComponent {
count$: Observable<number>;

constructor(private store: Store<AppState>) {
this.count$ = store.pipe(select('count'));
}
}

Effects

import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map, tap } from 'rxjs/operators';

@Injectable()
export class AuthEffects {
constructor(private actions$: Actions) {}

@Effect() authActions$ = this.action$.pipe(
ofType('LOGIN'),
tap(action => console.log(action)),
map(() => ({ type: 'LOGGED_IN' }))
);
}

Integrated Error Handling

Angular includes a built-in Error Handler for centralized error handling. Effects adds integration with this error handler, so instead of simply logging errors to the console, you can now integrate with your own custom error handling if your Effect throws an error.

Store Devtools Improvements

Store Devtools now includes optimizations when serializing state history, resulting in better overall performance. The Redux Devtools Extension includes support for disabling extension features in production. Store Devtools now includes a logOnly option so you can include the Devtools in your production build, but only provide access to logging the state along with the powerful time-traveling debugging tools.

import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';

@NgModule({
imports: [
StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument({
// Restrict extension to log-only mode
logOnly: environment.production
})
]
})
export class AppModule { }

Store Devtools have also been updated with support for custom sanitizers for actions and state. This is especially useful if you include your devtools in production, but want to keep any sensitive information from dispatched actions or state. Now you can strip or modify actions and state before its displayed in the extension.

import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';

@NgModule({
imports: [
StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument({
actionSanitizer: (action: Action, id: number) => {
return { type: 'SANITIZED_ACTION' };
},
stateSanitizer: (state: any, id: number) => {
return 'SANITIZED_STATE';
}
})
]
})
export class AppModule { }

Entity

Entity now includes new upsert adapter methods. The upsertOne and upsertMany methods insert new entities that aren’t currently present in the collection and update existing entities in the collection.

import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { User } from './user.model';
import { UserActions, UserActionTypes } from './user.actions';
export interface State extends EntityState<User> {}export const adapter: EntityAdapter<User> = createEntityAdapter<User>();export const initialState: State = adapter.getInitialState();export function reducer(
state = initialState,
action: UserActions
): State {
case UserActionTypes.UPSERT_USER: {
return adapter.upsertOne(action.payload.userUpdate, state);
}
case UserActionTypes.UPSERT_USERS: {
return adapter.upsertMany(action.payload.userUpdates, state);
}
default:
return state;
}

Schematics

NgRx Schematics is an exciting addition to the NgRx platform. For a more general introduction to schematics, see the Angular blog post. Whether you’re already using NgRx in your application, or introducing it into an existing application, schematics allow you to quickly build out feature areas using NgRx with the Angular CLI.

How to use

Use the Angular CLI’s generate command to scaffold out NgRx blueprints.

You can add state management with @ngrx/store to your application with developer tools enabled.

ng generate store State --root --module app.module.ts

You can setup your application with @ngrx/effects:

ng generate effect App --root --module app.module.ts

You can also generate a feature set, including actions, a reducer and effects.

ng generate feature User --module app.module.ts

These are just a few examples of blueprints you can use when scaffolding out features that use NgRx libraries. You can visit our github repo to find complete documentation on using NgRx Schematics.

Support NgRx

With NgRx 4 we announced the creation of our OpenCollective where you can help support the development of NgRx. We are thankful for the continued support from of our supporters and backers for the project. In addition to development efforts, we were also able to sponsor diversity tickets for NgAtlanta, which focused on diversity, inclusion and Angular. If you haven’t already, consider backing or sponsoring NgRx efforts through the OpenCollective.

--

--

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 💪🏿