How to upgrade your Angular and NgRx Apps to v8
Tags: angular, javascript, ngrx, showdev
Published: 2019-06-14 12:33:51

---
title: How to upgrade your Angular and NgRx Apps to v8
published: true
description: A detailed walkthrough on upgrading to Angular and NgRx 8 and making use of the new creator functions
tags: angular,javascript,ngrx,showdev
canonical_url: https://ultimatecourses.com/blog/how-to-upgrade-your-angular-and-ngrx-apps-to-v8
---

# Overview

Do you have an awesome application written with Angular v7 using NgRx v7, but have been feeling left out will all the mentions online and at conferences about Angular v8 and NgRx v8? Well, you are in luck! Today we will explore together, how to upgrade our applications to use Angular v8 using the Angular CLI tooling. We will also explore upgrading to NgRx v8. This will allow us to take advantage of the new features provided in NgRx v8. Included with NgRx v8 is a shiny set of creators, or type-safe factory functions, for actions, effects, and reducers. 

This article has been adapted from an original post on  [Ultimate Courses](https://ultimatecourses.com/blog/how-to-upgrade-your-angular-and-ngrx-apps-to-v8).


# Upgrading Dependencies

## Upgrading Angular

> The Angular team has provided a great website that walks through the process of upgrading in-depth. This website can be found at [Angular Update Tool](https://update.angular.io/). We will touch on some of the information today.

The first step is the process is to upgrade our application to Angular v8. We will use the Angular CLI to manage this process for us. 

This is the preferred method, as Angular has provided built-in migration scripts or schematics to alleviate some of the manual process involved had we just simply updated versions in our `package.json`.

Let's start by running the following command in the terminal:

Update the Global Angular CLI version

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

Update the core framework and local CLI to v8

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

> Throughout this process, we might encounter issues with third-party libaries. In those instances, it is best to visit the GitHub issues and repositories for those libraries for resolution.

## Upgrading NgRx

Now that we have upgraded our application to use Angular v8, let's proceed with updating NgRx to v8. We will make use of the Angular CLI here as well.

Update NgRx to v8

```shell
ng update @ngrx/store
```

The prior command should update our `package.json` dependencies and run any NgRx-provided migrations to keep our application in working order.

Depending on your setup, `ng update @ngrx/store` may not automatically update the additional `@ngrx/*` libraries that you have installed. If this happens, the best course is to manually run `npm install` for each additional module in use with NgRx.

Examples are as follows:

```shell
npm install @ngrx/entity@latest
npm install @ngrx/effects@latest
npm install @ngrx/data@latest
npm install @ngrx/router-store@latest
```

### NgRx Migration Guide

The NgRx team has provided a detailed migration guide for updating to NgRx v8. More information on upgrading to v8 of NgRx can be found here: [V8 Update Guide](https://ngrx.io/guide/migration/v8)

# Learn by Example - a Fruit Store (NgRx v7)

One of the most popular ways to learn new methods, is through code examples. Let's explore the following example of a simplified NgRx store that holds an `array` of `Fruit` objects. 

Each `Fruit` object consists of three properties `fruitId`, `fruitClass` and `fruitName`.

```typescript
interface Fruit {
    fruitId: number;
    fruitType: string;
    fruitName: string;
}
```

For example, if we had an `orange`, it might look something like this:

```typescript
const orange: Fruit = {
    fruitId: 1,
    fruitType: 'citrus',
    fruitName: 'orange'
};
```

## State

Exploring further, our `State` object in the NgRx store will contain properties like `fruits`, `isLoading`, and `errorMessage`. 

- `fruits` is defined as an `array` for `Fruit` objects
- `isLoading` is a `boolean` to keep track of when the store is in the process of loading data from an external API.
- `errorMessage` is a `string` property that is `null` unless an error has occurred while requesting data from an external API.

An example `State` `interface` might look like the following:

```typescript
interface State {
    fruits: Fruit[];
    isLoading: boolean;
    errorMessage: string;
}
```

An example store with `fruits` loaded might look like the following:

```typescript
const state: State = {
    fruits: [
        {
            fruitId: 1,
            fruitType: 'citrus',
            fruitName: 'orange'
        }
    ],
    isLoading: false,
    errorMessage: null
}
```

## Actions

Following proper redux pattern guidance, we cannot directly update state, so we need to define a set of actions to work with our state through a reducer. Let's imagine we have 3 actions for this example:

- `[App Init] Load Request` - This action is intended to be dispatched from our UI layer to indicate we are requesting to load `Fruit` objects into our store. This action does not have a payload or `props`.

- `[Fruits API] Load Success` - This action is intended to be dispatched from our effects when an `[App Init] Load Request` has been dispatched, an API has been called and successful response is received from the API. This action contains a payload or `props` object that includes the `array` of `Fruit` object to be loaded into our store.

- `[Fruits API] Load Failure` - This action is intended to be dispatched from our effects when an `[App Init] Load Request` has been dispatched, an API has been called and failure response is received from the API. This action contains a payload or `props` object that includes the error message of our API request, so that it can be loaded into our store.

### NgRx v7 Implementation

The actual NgRx v7 implementation of our actions might look something like the following:

```typescript
import { Action } from '@ngrx/store';
import { Fruit } from '../../models';

export enum ActionTypes {
  LOAD_REQUEST = '[App Init] Load Request',
  LOAD_FAILURE = '[Fruits API] Load Failure',
  LOAD_SUCCESS = '[Fruits API] Load Success'
}

export class LoadRequestAction implements Action {
  readonly type = ActionTypes.LOAD_REQUEST;
}

export class LoadFailureAction implements Action {
  readonly type = ActionTypes.LOAD_FAILURE;
  constructor(public payload: { error: string }) {}
}

export class LoadSuccessAction implements Action {
  readonly type = ActionTypes.LOAD_SUCCESS;
  constructor(public payload: { fruits: Fruit[] }) {}
}

export type ActionsUnion = LoadRequestAction | LoadFailureAction | LoadSuccessAction;
```

### NgRx v8 - Upgrading to createAction

> It's important to note, that while `createAction` is the hot new way of defining an `Action` in NgRx, the existing method of defining an `enum`, `class` and exporting a type union will still work just fine in NgRx v8.

Beginning with version 8 of NgRx, actions can be declared using the new `createAction` method. This method is a `factory function`, or a `function` that returns a `function`. 

According to the [official NgRx documentation](https://ngrx.io/guide/store/actions#writing-actions), "The `createAction` function returns a function, that when called returns an object in the shape of the `Action` interface. The `props` method is used to define any additional metadata needed for the handling of the action. Action creators provide a consistent, type-safe way to construct an action that is being dispatched."

In order to update to `createAction`, we need to do the following steps:

1. Create a new `export const` for our action. If our action has a payload, we will also need to migrate to using the `props` method to define our payload as `props`.

Example for `[App Init] Load Request`

```typescript
// before
export class LoadRequestAction implements Action {
  readonly type = ActionTypes.LOAD_REQUEST;
}
```

```typescript
// after
export const loadRequest = createAction('[App Init] Load Request');
```

Example for `[Fruits API] Load Success`

```typescript
// before
export class LoadSuccessAction implements Action {
  readonly type = ActionTypes.LOAD_SUCCESS;
  constructor(public payload: { fruits: Fruit[] }) {}
}
```

```typescript
// after
export const loadSuccess = createAction('[Fruits API] Load Success', props<{fruits: Fruit[]}>());
```

2. Remove the old action from the `ActionTypes` `enum`

3. Remove the old action from the `ActionsUnion`

Our final migrated actions file might look something like this:

```typescript
import { Action, props } from '@ngrx/store';
import { Fruit } from '../../models';

export const loadRequest = createAction('[App Init] Load Request');
export const loadFailure = createAction('[Fruits API] Load Failure', props<{errorMessage: string}>());
export const loadSuccess = createAction('[Fruits API] Load Success', props<{fruits: Fruit[]}>());
```

As we can see, this is a huge reduction in code, we have gone from 24 lines of code, down to 6 lines of code.

### NgRx v8 - Dispatching createAction Actions 

A final note is that we need to update the way we dispatch our actions. This is because we no longer need to create `class` instances, rather we are calling `factory` functions that return an object of our action.

Our before and after will look something like this:

```typescript
// before 
this.store.dispatch(new featureActions.LoadSuccessAction({ fruits }))

// after
this.store.dispatch(featureActions.loadSuccess({ fruits }))
```

## Reducer

Continuing with our example, we need a reducer setup to broker our updates to the store. Recalling back to the redux pattern, we cannot directly update state. We must, through a pure function, take in current state, an action, and return a new updated state with the action applied. Typically, reducers are large `switch` statements keyed on incoming actions.

Let's imagine our reducer handles the following scenarios:

- On `[App Init] Load Request` we want the state to reflect the following values: 
    - `state.isLoading: true`
    - `state.errorMessage: null`

- On `[Fruits API] Load Success` we want the state to reflect the following values: 
    - `state.isLoading: false`
    - `state.errorMessage: null`
    - `state.fruits: action.payload.fruits`

- On `[Fruits API] Load Failure` we want the state to reflect the following values: 
    - `state.isLoading: false`
    - `state.errorMessage: action.payload.errorMessage`

### NgRx v7 Implementation

The actual NgRx v7 implementation of our reducer might look something like the following:

```typescript
import { ActionsUnion, ActionTypes } from './actions';
import { initialState, State } from './state';

export function featureReducer(state = initialState, action: ActionsUnion): State {
  switch (action.type) {
    case ActionTypes.LOAD_REQUEST: {
      return {
        ...state,
        isLoading: true,
        errorMessage: null
      };
    }
    case ActionTypes.LOAD_SUCCESS: {
      return {
        ...state,
        isLoading: false,
        errorMessage: null,
        fruits: action.payload.fruits
      };
    }
    case ActionTypes.LOAD_FAILURE: {
      return {
        ...state,
        isLoading: false,
        errorMessage: action.payload.errorMessage
      };
    }
    default: {
      return state;
    }
  }
}
```

### NgRx v8 - Upgrading to createReducer

> It's important to note, that while `createReducer` is the hot new way of defining a reducer in NgRx, the existing method of defining a `function` with a `switch` statement will still work just fine in NgRx v8.

Beginning with version 8 of NgRx, reducers can be declared using the new `createReducer` method. 

According to the [official NgRx documentation](https://ngrx.io/guide/store/reducers#creating-the-reducer-function), "The reducer function's responsibility is to handle the state transitions in an immutable way. Create a reducer function that handles the actions for managing the state using the `createReducer` function."

In order to update to `createReducer`, we need to do the following steps:

1. Create a new `const reducer = createReducer` for our reducer.
2. Convert our `switch` `case` statements into `on` method calls. Please note, the `default` case is handled automatically for us. The first parameter of the `on` method is the action to trigger on, the second parameter is a handler that takes in `state` and returns a new version of `state`. If the action provides `props`, a second optional input parameter can be provided. In the example below we will use destructuring to pull the necessary properties out of the `props` object.
3. Create a new `export function reducer` to wrap our `const reducer` for `AOT` support.

Once completed, our updated `featureReducer` will look something like the following:

```typescript
import { createReducer, on } from '@ngrx/store';
import * as featureActions from './actions';
import { initialState, State } from './state';
...
const featureReducer = createReducer(
  initialState,
  on(featureActions.loadRequest, state => ({ ...state, isLoading: true, errorMessage: null })),
  on(featureActions.loadSuccess, (state, { fruits }) => ({ ...state, isLoading: false, errorMessage: null, fruits })),
  on(featureActions.loadFailure, (state, { errorMessage }) => ({ ...state, isLoading: false, errorMessage: errorMessage })),
);

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

## Effects

Because we want to keep our reducer a pure function, it's often desirable to place API requests into `side-effects`. In NgRx, these are called `Effects` and provide a reactive, RxJS-based way to link actions to observable streams.

In our example, we will have an `Effect` that `listens` for an `[App Init] Load Request` Action and makes an HTTP request to our imaginary `Fruits API` backend. 

- Upon a successful result from the `Fruits API` the response is mapped to an `[Fruits API] Load Success` action setting the payload of `fruits` to the body of the successful response.

- Upon a failure result from the `Fruits API` the error message is mapped to an `[Fruits API] Load Failure` action setting the payload of `errorMessage` to the error from the failure response.

### NgRx v7 Implementation

The actual NgRx v7 implementation of our effect might look something like the following:

```typescript
@Effect()
  loadRequestEffect$: Observable<Action> = this.actions$.pipe(
    ofType<featureActions.LoadRequestAction>(
      featureActions.ActionTypes.LOAD_REQUEST
    ),
    concatMap(action =>
      this.dataService
        .getFruits()
        .pipe(
          map(
            fruits =>
              new featureActions.LoadSuccessAction({
                fruits
              })
          ),
          catchError(error =>
            observableOf(new featureActions.LoadFailureAction({ errorMessage: error.message }))
          )
        )
    )
  );
```

### NgRx v8 - Upgrading to createEffect

> It's important to note, that while `createEffect` is the hot new way of defining a reducer in NgRx, the existing method of defining a class property with an `@Effect()` decorator will still work just fine in NgRx v8.

Beginning with version 8 of NgRx, effects can be declared using the new `createEffect` method, according to the [official NgRx documentation](https://ngrx.io/guide/effects#writing-effects). 

In order to update to `createEffect`, we need to do the following steps:

1. Import `createEffect` from `@ngrx/effects`
2. Remove the `@Effect()` decorator
3. Remove the `Observable<Action>` type annotation
4. Wrap `this.actions$.pipe(...)` with `createEffect(() => ...)`
5. Remove the `<featureActions.LoadRequestAction>` type annotation from `ofType`
6. Change the `ofType` input parameter from `featureActions.ActionTypes.LOAD_REQUEST` to `featureActions.loadRequest`
7. Update the action calls to remove `new` and to use the creator instead of `class` instance. For example, `new featureActions.LoadSuccessAction({fruits})` becomes `featureActions.loadSuccess({fruits})`.

Once completed, our updated `loadRequestEffect` will look something like the following:

```typescript
  loadRequestEffect$ = createEffect(() => this.actions$.pipe(
        ofType(featureActions.loadRequest),
        concatMap(action =>
        this.dataService
            .getFruits()
            .pipe(
                map(fruits => featureActions.loadSuccess({fruits})),
                catchError(error =>
                    observableOf(featureActions.loadFailure({ errorMessage: error.message }))
                )
            )
        )
    )
  );
```

# Full Video Walkthrough

If you would like to watch a full video walkthrough here you go.

{% youtube 0LK73MdhED4 %}

# Conclusion

This brings us to the end of this guide. Hopefully you've been able to learn about upgrading your application to Angular v8 and NgRx v8. In addition, you should feel confident in taking advantage of some of the new features available in NgRx v8 to reduce the occurrence of what some might refer to as boilerplate. Happy updating and upgrading!