Announcing NgRx Version 7 — Docs, Testing, and more

@ngrx
@ngrx
Published in
7 min readJan 21, 2019

Today we are announcing the version 7 release of the NgRx platform. This release contains bug fixes, new features, and some breaking changes, all aimed at improving the developer experience when using NgRx libraries. There are also updates to announcements with version 6.

Official Docs
In case you haven’t noticed already, NgRx has an official documentation site at https://ngrx.io! The documentation site is a PWA built with Angular using a similar infrastructure, look, and feel to what you see on the Angular docs. This has been a long-awaited feature, and will give us a space for tutorials, guides, real-world examples, and recipes covering advanced topics. We will continue to add new content to the documentation site that will help developers learn the “why” behind NgRx and the “how” when using it.

Contributing is also very simple, as you can edit any page using the pencil icon in the top right corner of each page. This opens a GitHub editor where you can edit the markdown files quickly and submit pull requests. Previews of your changes are generated with your pull request for quicker feedback and turnaround. All of the existing documentation has been moved to the new site, along with a new tutorial, and refreshed guides! Be sure to check out the site at https://ngrx.io. Feel free to file new issues and feature requests for the docs on our GitHub page.

Breaking Changes
Deprecated in version 6.1, the ofType method on the Actions class in @ngrx/effects class was removed. This change was made to align with the pipeable operators introduced in RxJS V6.

Before:

import { Effect, Actions } from '@ngrx/effects';@Injectable()
export class MyEffects {
@Effect()
someEffect$: Observable<Action> = this.actions$
.ofType(UserActions.LOGIN)
.pipe(map(() => new AnotherAction()));
constructor(private actions$: Actions) {}
}

After:

// import ofType operator
import { Effect, Actions, ofType } from '@ngrx/effects';
@Injectable()
export class MyEffects {
@Effect()
someEffect$: Observable<Action> = this.actions$.pipe(
ofType(UserActions.LOGIN), // use the pipeable ofType operator
map(() => new AnotherAction())
);
constructor(private actions$: Actions<UserActions>) {}
}

This along with the addition of a generic type to the Actions class provides a more type-safe way to infer the type of the actions in your effects class.We have released a standalone tool to aid you in your migration to the new operator syntax. We are also exploring the option of a migration integrated with the Angular CLI to make this transition easier. As with each major release, we have also updated to the Angular V7 and RxJS 6.3 dependencies. Updating all your packages to the latest version can be done using the Angular CLI command, ng update.

ng update @ngrx/store

There are additional minor breaking changes with the necessary changes listed in our V7 migration guide.

New Features
We also introduced some new features in version 7 across many of the NgRx libraries including deeper integration with the Angular CLI, more support for the Redux Devtools Extension features, and testing just to name a few. Many of these features were requested and developed by community contributors. Some of the highlighted features are listed below.

Store

Selector Props
In V7, we introduced two new features for interacting with the Store during development and testing. Now with selectors, you can use props to provide additional information needed for computing data models. Whether you need to pass an id from the router, or provide some static data, props give you this functionality with a selector out of the box.

Create a selector that uses props:

export const getCount = createSelector(
getCounterValue,
(counter, props) => counter * props.multiply);

And define the props in the select operator:

this.store.pipe(select(fromRoot.getCount, { multiply: 2 }))

Testing Package
In an effort to make testing using Store easier, we have added a testing package for mocking out the state used by the Store. The provideMockStore() method allows you to provide a mock store to push state changes during unit testing as an alternative to providing your reducers. Now you can completely test your Store-aware components and effects in isolation with less setup.

import { Store } from '@ngrx/store';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { take } from 'rxjs/operators';
describe('Mock Store', () => {
let mockStore: MockStore<{ counter1: number, counter2: number }>;
beforeEach(() => {
const initialState = { counter1: 0, counter2: 1 };
TestBed.configureTestingModule({
providers: [
provideMockStore({ initialState })
],
});
mockStore = TestBed.get(Store);
});
it('should set the new state', () => {
mockStore.setState({ counter1: 1, counter2: 2 });
mockStore.pipe(take(1)).subscribe(state => {
expect(state.counter1).toBe(1);
});
});
});

Effects

Lifecycle hooks
To give more insight into the Effects lifecycle, we introduced new lifecycle interfaces, OnInitEffects and OnIdentifyEffects. When implemented on your effects class, the OnInitEffects lifecycle method is called after the effects are registered.

Here you can provide any initialization logic, and return an action that is dispatched to the store.

import { OnInitEffects } from '@ngrx/effects';class UserEffects implements OnInitEffects {
ngrxOnInitEffects(): Action {
return { type: '[UserEffects]: Init' };
}
}

The OnIdentifyEffects is a more advanced hook that gives you control over unique instances of your Effects classes. For each unique identifier, a separate instance effect is created.

import { OnIdentifyEffects } from '@ngrx/effects';class EffectWithIdentifier implements OnIdentifyEffects {
constructor(private effectIdentifier: string) {}
ngrxOnIdentifyEffects() {
return this.effectIdentifier;
}
}

Entity

New Adapter Methods
Entity is all about managing collection, so we updated and additional adapter methods to use when dealing with collections, including mapping, removing, and deleting entities. The map method is similar to the Array.map method, iterating over your collection, allowing you to make updates to entities in your collection using a predicate function. The updateMany and removeMany methods now also support a predicate method to give you more control over which entities to update and remove based on a predicate function.

Router Store

New Actions
To further integrate with the Angular Router, we have introduced new actions that provide more information about the state of the router in your store. The new actions include when the router has started a new navigation, as well as when a navigation cycle has successfully completed. This gives you access to more of the router state after guards and resolvers have finished running. All these new actions are provided with more descriptive action types for the existing actions, so you can easily glance at the developer tools to see when the actions are triggered.

Store Devtools

Extension features
To enhance developer productivity with the Redux Devtools Extension, we have added support for more extension features, including blacklisting and white-listing of actions, persisting state across page reloads, locking, and pausing of the extension. The new options are fully configurable through the StoreDevtools instrumentation, giving you the flexibility to turn features on and off as needed.

To see the full list of new features, look at our release changelog.

Updates

NgRx Data
With V6, we announced that Tim Deschryver, John Papa and Ward Bell were joining the NgRx team delivering high-quality libraries for the platform. We are continuing to work with John and Ward to integrate the ngrx-data library officially into the platform as a first-party package. NgRx Data provides an out of the box solution for managing large sets of entity collections with external APIs, simple configuration, and customization options. Along with integrating NgRx Data, are still working on new APIs for server-side rendering, serialization, and exploring new functionality that will be provided with the Ivy renderer in Angular. We also welcome new ideas, so if you have any, feel free to open an issue.

Official NgRx Workshop!
The NgRx team will be at ng-conf 2019 in a big, albeit different way this year! Last year, we were part of a complete fair-day track during ng-conf dedicated to NgRx and its ecosystem. This year we will be providing an official workshop! The “NgRx: A Reactive State of Mind” workshop is a full 2-day workshop not just to learn how NgRx works, but to learn the foundations of the framework, best practices, and how to think reactively when using NgRx. We will work through the NgRx architecture in-depth with practical examples for state management, data models using selectors, side effects, and testing. Whether you’re just starting with NgRx, or you’re already using it, there will be something for you at this workshop. Visit the registration page to sign up.

Thanks
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 to the latest version of NgRx including: kouMatsumoto, UncleJimmy, dummdidumm, kanafgan, tja4472, peterbsmith2, Guillaume de Jabrun, SerkanSipahi, cmckni3, patrickmcd, matepapp, alex-okrushko, rkirov, krzysztof-grzybek, xxluke, TeoTN, thefliik, icepeng, myspivey, wesleygrimes, null-reference, joostme, LukeHowellDev, baumandm, maxime1992, roopkt, bagbag, luchsamapparat, Fost, bcbanes, Teamop, seekheart, adrianfaciu, rafa-as, ngfelixl, sheikalthaf, itayod, karanveersp, and emilio-martinez. If you are interested in contributing, visit our GitHub page and look through our open issues, some marked specifically for new contributors.

Along with the community, we cannot sustain NgRx without the help of our past and present backers and sponsors. Whether it be $2, $5, or more, our monthly backers have continued to support our efforts in developing and maintaining the platform. Our bronze level sponsors include Oasis Digital, Lukas Ruebbelke, Alex Okrushko, along with a significant contribution from Deborah Kurata.

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.

NgRx requires significant time and effort that often goes unpaid, and we would like to change that. If you or your company wants to contribute to NgRx as a backer or sponsor, please visit our OpenCollective page for different contribution options or contact us directly for other sponsorship opportunities.

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

--

--