---
title: "Faster App Development with NgRx 8"
description: "NgRx 8 features improved developer ergonomics, less boilerplate, runtime checks, and easier error handling."
authors:
  - name: "Sam Julien"
    url: "https://auth0.com/blog/authors/sam-julien/"
date: "Jul 3, 2019"
category: "Developers,Whats New,NgRx"
tags: ["angular", "rxjs", "ngrx"]
url: "https://auth0.com/blog/faster-app-development-with-ngrx-8/"
---

# Faster App Development with NgRx 8


**TL;DR:** NgRx 8 introduces a host of improvements, including `createAction`, `createReducer`, and `createEffect`. These helper functions drastically reduce (no pun intended) boilerplate, which boosts developer productivity.

## NgRx 8: A Massive Win
Shortly after the [release of Angular 8](https://auth0.com/blog/angular-8-differential-loading/), the NgRx team released their own version 8. It was a big release full of fantastic improvements to the library. While I'll let you read the [official release announcement](https://medium.com/ngrx/announcing-ngrx-version-8-ngrx-data-create-functions-runtime-checks-and-mock-selectors-a44fac112627) by [Tim Deschryver](https://twitter.com/tim_deschryver), here are the highlights:

- [`angular-ngrx-data`](https://github.com/johnpapa/angular-ngrx-data) by [John Papa](https://twitter.com/John_Papa) and [Ward Bell](https://twitter.com/wardbell) is now officially part of NgRx as [`@ngrx/data`](https://github.com/ngrx/platform/tree/master/modules/data)
- [Runtime checks](https://ngrx.io/guide/store/configuration/runtime-checks) are now available to check that state and actions aren't mutated and are serializable (these replace the `ngrx-store-freeze` package)
- Fully isolated unit tests are now available thanks to [mock selectors](https://ngrx.io/guide/store/testing#using-mock-selectors)
- There have been a couple of improvements to `@ngrx/router`, including a new [minimal `routerState` option](https://next.ngrx.io/guide/router-store/configuration)
- There are now NgRx snippets in John Papa's [Angular Snippets](https://marketplace.visualstudio.com/items?itemName=johnpapa.Angular2) VS Code extension
-  [Alex Okrushko](https://twitter.com/AlexOkrushko) and [Wes Grimes](https://twitter.com/wesgrimes) have joined the NgRx team (well deserved!)
  
I've saved the best for last, though, and it's the subject of this article:

- `createAction`, `createReducer`, and `createEffect` helper methods *drastically* reduce boilerplate and improve development time

We're going to dig into what that means and how these functions will make your life better, but before we do that, we should make sure you know how to update to version 8 to take advantage of these new features.

<include src="TweetQuote" quoteText="NgRx 8 features improved developer ergonomics, less boilerplate, runtime checks, and easier error handling!"/>

## How to Update to NgRx 8
In order to update to NgRx 8, you'll need to be sure your project is updated to Angular 8. You can update your Angular CLI globally by running this command:

```bash
npm install -g @angular/cli
```

In a project that needs to be updated to Angular 8, you can run the following:

```bash
ng update @angular/cli @angular/core
```

You can then run the following to update to NgRx 8:

```bash
ng update @ngrx/store
```

When working on this article, I ran into a bit of a problem with the TypeScript version. It seems like there was a conflict between the required versions, so I had to manually lock in version `3.4.3`.

If you're using `ngrx-data`, you can easily migrate to `@ngrx/data` with this command:

```bash
ng add @ngrx/data --migrate
```

For a more thorough explanation of this process, Wes Grimes has written a great article on how to [upgrade to Angular 8 and NgRx 8](https://dev.to/angular/how-to-upgrade-your-angular-and-ngrx-apps-to-v8-4iip). For more specific details on migration to NgRx 8, check out the official [migration guide](https://ngrx.io/guide/migration/v8). Finally, don't forget that Angular has an [official update tool](https://update.angular.io) to help with moving to new versions of Angular.

With that out of the way, let's get to the fun stuff!

## createExcitement: The New NgRx 8 Helper Functions
One of the most common complaints about NgRx (and the Redux pattern in general) is that there is too much boilerplate. Once you dig into the library and the pattern, though, you start to understand that the initial setup is a completely worthwhile investment when you're managing state in large, complex applications (which is what NgRx is designed for!).

That being said, the NgRx team has listened to the developer community and made some huge improvements in "developer ergonomics" (a fancy way to say making it easier to write code) with version 8. Most of these improvements are due to a refactor of how actions, reducers, and effects are set up. There are now helper methods that are easy to understand and take less code to write. Let's take each of them in turn.

### createAction
As my friend [Mike Ryan](https://twitter.com/MikeRyanDev) says, "Actions are the gluten of the NgRx loaf." Indeed, they are the core of any NgRx application. Great care and attention are required in deciding what actions your app needs. Unfortunately, actions take a lot of code to set up. Just look at this excerpt from the application we built in my original [NgRx Authentication](https://auth0.com/blog/ngrx-authentication-tutorial/) tutorial:

```typescript
// src/auth/actions/auth.actions.ts (excerpt)
export enum AuthActionTypes {
  Login = '[Login Page] Login',
  LoginComplete = '[Login Page] Login Complete',
  LoginFailure = '[Auth API] Login Failure'
}

export class Login implements Action {
  readonly type = AuthActionTypes.Login;
}

export class LoginComplete implements Action {
  readonly type = AuthActionTypes.LoginComplete;
}

export class LoginFailure implements Action {
  readonly type = AuthActionTypes.LoginFailure;

  constructor(public payload: any) {}
}

export type AuthActions =
  | Login
  | LoginComplete
  | LoginFailure;
```

This excerpt only contains three of the eight actions in that application and it's a very small app! As Alex Okrushko points out in his excellent article on [the new action creators](https://blog.angularindepth.com/ngrx-action-creators-redesigned-d396960e46da), enums and strings also make it very difficult to see where actions are used. And don't get me started on those union types! You can see why a change was needed.

Enter the new `createAction` method. With `createAction`, you pass in the action name along with an optional `props` function with a specified argument type as a destructured object. 

Yikes, that's a lot of jargon. Let me explain that with an example. 

Let's say I have an action called `booksLoaded` that needs to receive an array of books (`books`) of type `Book[]` when created. My `props` function for `createAction` would be `props<{ books: Book[] }>()`. (With [destructuring](https://auth0.com/blog/a-rundown-of-es6-features/#ECMAScript-2015-Features), `{ books }` is the equivalent of `{ books: books }`.)  

```typescript
export const booksLoaded = createAction(
  '[Books API] Books Loaded', 
  props<{ books: Book[] }>()
  );
```

That way, when I create a new action of this type, I can directly pass the array of books into the constructor: `new booksLoaded({ booksFromServer })`.

So, the above authentication actions would be refactored like so:

```typescript
export const login = createAction('[Login Page] Login');

export const loginComplete = createAction('[Login Page] Login Complete');

export const loginFailure = createAction(
  '[Auth API] Login Failure', 
  props<{ error: any }>()
);
```

Mind-blowing, right?

There are two things to notice here. First, notice that the action constant names have gone from Pascal case (`LoginFailure`) to camel case (`loginFailure`). This is due to actions changing from classes to functions and is a standard JavaScript style convention. Don't let that trip you up, but be mindful of that in refactoring.

Second, notice that I renamed `payload` to `error` because it is more descriptive. (I could have also given it a new type like `Error`, but it doesn't matter much in this example). While this is a great new feature with the redesigned action creator function, be careful of doing this. Do a search through your code to avoid breaking other parts of the app relying on a `payload` property (a great reminder from [Gregor Woiwode](https://medium.com/@gregor.woiwode/ngrx-8-meet-the-new-upcoming-factory-methods-of-the-next-major-release-a97a079cc089)). If you rename `payload` in the action creator, be sure to change it everywhere.

There's one last great feature of the new action creators. You can now specify a default value of a `prop` argument. For example, in the above `loginFailure` action, I could provide a default error message:

```typescript
export const loginFailure = createAction(
  '[Auth API] Login Failure',
  (errorMessage = 'Error logging in') => ({ payload: { errorMessage }})
);
```

This would be a great backup in case the server fails to provide an error message for some reason.

To add one of these new action creators to your application, you can use the [updated action schematic](https://ngrx.io/guide/schematics/action):

```bash
ng generate @ngrx/schematics:action myNewAction --creators
```

This command will generate a new file called `my-new-action.actions.ts` containing a constant named `loadMyNewAction` using the `createAction` function.

<include src="TweetQuote" quoteText="The new action creators of NgRx 8 drastically reduce (no pun intended) development time when adding new features!"/>

### createReducer
The new way to create actions is incredible, but it doesn't stop there. Reducers are also now easier to write thanks to the `createReducer` method.

Here's a typical example of a reducer you might find in a burger restaurant app:

```typescript
export function reducer(
  state = initialState,
  action: BurgerApiActionsUnion
): State {
  switch (action.type) {
    case BurgerApiActionTypes.LoadBurgerCollection: {
      return { 
        ...state
        loading: true
      };
    }

    case BurgerApiActionTypes.LoadBurgersSuccess: {
      return { 
        loaded: true,
        loading: false,
        ids: action.payload.map(burger => burger.id)
      };
    }

    default: {
      return state;
    }
  }
}
```

This is a simple example, but as it scales up, you'll have a ton of case statements that will make understanding this code difficult. It gets messy fast (just like eating burgers, really).

With NgRx 8, you can use `createReducer` instead:

```typescript
const burgerReducer = createReducer(
  initialState,
  on(BurgerApiActionTypes.loadBurgerCollection, state => ({
    ...state,
    loading: true
  })),
  on(BurgerApiActionTypes.loadBurgersSuccess, (state, { burgers }) => ({
    loaded: true,
    loading: false,
    ids: burgers.map(burger => burger.id)
  }))
);
```

Much cleaner, isn't it? Each case uses the `on` function that receives the action and a function to modify state. 

The `on` function can also take multiple actions, making it easy to grow the reducer function. For example, it's common for the success of a record addition and the failure of a record deletion to result in the same state. An example of this is when an app state includes both a collection of data (which should match what's on the server) and an array of IDs for faster lookup (which is maintained in memory). In order to make sure the array of IDs always matches what's on the server, it's necessary to account for failures of adding or deleting records.

Here's an example of that with the burger application:

```typescript
const burgerReducer = createReducer(
  // ...other cases,
  on(
    CollectionApiActions.addBurgerSuccess,
    CollectionApiActions.removeBurgerFailure,
    (state, { burger }) => {
      if (state.ids.indexOf(burger.id) > -1) {
        return state;
      }
      return {
        ...state,
        ids: [...state.ids, burger.id],
      };
    }
  ),
  on(
    CollectionApiActions.removeBurgerSuccess,
    CollectionApiActions.addBurgerFailure,
    (state, { burger }) => ({
      ...state,
      ids: state.ids.filter(id => id !== burger.id),
    })
  )
);
```

Using the same reducer cases for multiple actions makes it easier to understand what's happening in this application in addition to ensuring the `ids` array doesn't get out of sync with the server.

One other important note on using `createReducer`. As of this writing, the Angular ahead-of-time (AOT) compiler (the compiler used for producing production builds) [does not support function expressions](https://angular.io/guide/aot-compiler#function-calls-are-not-supported). It's therefore necessary to wrap the `createReducer` function in an exported function like so:

```typescript
export function reducer(state: State | undefined, action: Action) {
  return burgerReducer(state, action);
}
```

Finally, as with `createAction`, there's a [schematic for the new reducer style](https://ngrx.io/guide/schematics/reducer):

```bash
ng generate @ngrx/schematics:reducer myNewReducer --creators
```

This schematic will generate a new file called `my-new-reducer.reducer.ts`. It will include both the `createReducer` constant and the exported `reducer` function for AOT.

### createEffect
Finally, `createEffect` is here to improve writing effects. Previously, effects used an `@Effect()` decorator. While this was fine, it was sort of the odd bird compared to all of the other more functional approaches NgRx takes.

Going back to the burger application, here's an example of the old style of effect: 

```ts
@Effect()
loadBurgerCollection$ = this.actions$.pipe(
  ofType(BurgerApiActionTypes.LoadBurgerCollection),
  switchMap(() =>
    this.burgerService.getAllBurgers().pipe(
      map((burgers: Burger[]) =>
        BurgerApiActions.LoadBurgersSuccess({ burgers })
      ),
      catchError(error =>
        of(BurgerApiActions.LoadBurgersFailure({ error }))
      )
    )
  )
);
```

The new `createEffect` helper simplifies this a bit and standardizes it to look more like creating actions, reducers, and selectors:

```typescript
loadBurgerCollection$ = createEffect(() =>
  this.actions$.pipe(
    ofType(BurgerApiActionTypes.loadBurgerCollection),
    switchMap(() =>
      this.burgerService.getCollection().pipe(
        map((burgers: Burger[]) =>
          BurgerApiActions.loadBooksSuccess({ burgers })
        ),
        catchError(error =>
          of(BurgerApiActions.loadBooksFailure({ error }))
        )
      )
    )
  )
);
```

> Remember, the actions have changed from Pascal case to camel case since they've changed from classes to functions.

There's also a small modification in effects that don't dispatch new actions. Here's an effect that fires after a burger is successfully ordered, which redirects back to the home page and doesn't dispatch a new action:

```typescript
@Effect({ dispatch: false })
orderBurgerSuccess$ = this.actions$.pipe(
  ofType(BurgerApiActions.OrderBurgerSuccess),
  tap(() => {
    this.router.navigate(['/']);
  })
);
```

Using the new `createEffect` function, you can refactor this code to the following:

```typescript
orderBurgerSuccess$ = createEffect(() => 
  this.actions$.pipe(
    ofType(BurgerApiActions.LoginSuccess),
    tap(() => this.router.navigate(['/']))
  ),
  { dispatch: false }
);
```

That second argument of the `createEffect` function is for passing in metadata to control how the effect operates.

One final word on effects in NgRx 8. Previously, the team found that developers were either forgetting to handle errors in their effects or handling them incorrectly. To help with this, effects now automatically resubscribe on errors (instead of completing) so they continue to listen to dispatched actions. This is extremely helpful but it can also be disabled if you start noticing weird behaviors. Simply pass `{ resubscribeOnError: false }` as the second argument of the `createEffect` function. 

As with the other two examples, there's a [schematic to add the new style of effect](https://ngrx.io/guide/schematics/effect) to your application:

```bash
ng generate @ngrx/schematics:effect myNewEffect --creators
```

This command will generate a new file called `my-new-effect.effects.ts` that imports `createEffect` and creates a class marked with the `Injectable` decorator.

## Aside: You Might Need Authentication (Even Though "You Might Not Need NgRx")
Most applications these days are going to need some sort of identity management to persist user profile information and handle authentication and authorization. To implement an identity management strategy in your NgRx application, some of the syntax has changed with version 8, but the core principles remain the same. You'll use actions for logging in and logging out and effects for calling your authentication service, while your reducer handles modifications to state like logged in status and profile attributes.

I cover this at length in my [NgRx authentication tutorial](https://auth0.com/blog/ngrx-authentication-tutorial/). Go ahead and <a href="https://auth0.com/signup" data-amp-replace="CLIENT_ID" data-amp-addparams="anonId=CLIENT_ID(cid-scope-cookie-fallback-name)">sign up for a free Auth0 account</a> and dig in to the tutorial to get started.

![Auth0's Lightweight Universal Login modal window](https://images.ctfassets.net/23aumh6u8s0i/54lZ5srDBAM0dqWSRkdxXk/f4260dcf2af6e7b5b4a52c62769e0745/lightweight-login)

By the way, I'd love to hear how it goes while using the new helper functions in version 8 of NgRx, so reach out on our [Community Forum](https://community.auth0.com/) any time.

## Conclusion
I don't know about you, but I couldn't be happier with NgRx 8. This is a team of volunteers who are making great software and even writing [phenomenal docs](https://ngrx.io/docs). With all of the improvements in this version, the future is looking bright. Give it a test drive and let me know how it goes!
