Ngrx Effects - Isolate side-effects in angular applications
Tags: angular, javascript, typescript, all
Published: 2020-09-15 22:22:22

---
title: Ngrx Effects - Isolate side-effects in angular applications
published: true
date: 2020-09-15 00:00:00 UTC
tags: angular,javascript,typescript,all
canonical_url: http://www.initgrep.com/posts/javascript/angular/handle-side-effects-in-angular-ngrx
---

## what is a Side-effect?

A [side effect](http://en.wikipedia.org/wiki/Side_effect_%28computer_science%29) refers simply to the modification of some kind of state - for instance:
- _Changing the value of a variable;_
- _Writing some data to disk;_
- _Enabling or disabling a button in the User Interface._

…[source](https://softwareengineering.stackexchange.com/questions/40297/what-is-a-side-effect)
 

##### Table of contents

- **Why NgRx Effects?**
  - Service based design vs NgRx Effects based design
- **NgRx Effects**
  - Installation
  - Implementation
  - Register NgRx Effects in module
 

## Why NgRx Effects?

A pure component has an immutable input and produces the events as output. These components are essentially dumb and most of the computations are done outside of it. A pure component has a single responsibility similar to _pure functions_.

Now, If the components are not doing any computations, most of the computations and side-effects would be moved inside the services. That is the first-hand use of angular services. It is easy to inject them into components and perform various computations.

Now here are a few things you should consider -

- First of all, if your application is growing fast and you are storing/managing state inside your components or services, you should consider a state management solution.
- The services are an ideal choice but you have to manually take care of storing the state, making sure the state remains immutable, consistent, and available for all the dependent components as well as services.
- Let’s assume, you have a service taking care of communicating via APIs to some remote server. You inject the service in a component and call the method of the service inside the component.
- …and if you have another service, which performs some computation which is supposed to be run when the user interacts with UI such as a click of a button. Again, you would inject the service in component, and on `click` of the button, a method of the service is called.

It works great… But if you notice, the component is tighly coupled with the service and it knows about what operations to perform when a user _clicks a button_ or when an API should be called.

The very first **disadvantage** of this pattern you would come across is **_components are hard to test since they are dependent on many services_**. You would also notice that It is almost **_impossible to reuse the components_**.

**_So what is the alternative approach?_** …

The alternative approach is to let components be pure and not responsible for managing the state . Instead make them reactive so that when an input data is available, it renders it to UI and when there are UI interactions, it generates the relevant Events.

That is it…

The component does not have to know, how the Input data is made available or how the events are handled.

**The services are nevertheless an important part of the application. They would still contain all the methods to do various computations or communicate via APIs. But now they are no longer being injected inside the component.**

I have already written a post about [reactive state management using NgRx store, actions, and selectors.](/igagrock/reactive-state-management-in-the-angular-ngrx-store-actions-selectors-4ap6) You can go through it to have an understanding of NgRx state management.

Let’s see a comparison between the service-based design and NgRx effects.

You might notice fewer elements in play during service-based design but don’t let it fool you. It is better to have more elements in application than to have a lousy app.

### Service based design
Suppose, our `AppComponent `requires a list of users.
- We have a service `AppRemoteService` and it contains `users$ observable` which can be subscribed to get a list of users.

```
users$ = this.httpClient.get<User[]>(URL).pipe(take(1));

```
- We have injected the `AppRemoteService` in side the `AppComponent` and we would subscribe to `AppRemoteService.users$` observable .

```
@Component({
    template: `
    <div class="user-container" 
      *ngIf="localUsers">
     <app-user *ngfor="let user of localUsers" 
                [inputUser]="user">
  </div>
    `
})
export class AppComponent{
//state inside component
localUsers: User[];
  
constructor(private remoteService: RemoteService){}
  
  ngOnInit(){
      //handle the subscription here
  this.remoteService.users$.subscrible(
      users => this.localUsers = users;
      );
  }
  } 

```

### NgRx Effects based design

Here is how NgRx effects will change it -

- The AppComponent would only require `NgRx Store` to select the `state` or dispatch `actions`.

```
export class AppComponent implements OnInit {
 constructor(private store: Store<fromApp.AppState>) { }
 }

```
- As soon as the component requires the list of users, it would dispatch an action `loadUsers` when the component is initialized.

```
export class AppComponent implements OnInit {
 constructor(private store: Store<fromApp.AppState>) { }
  
 ngOnInit(): void {
     //action dispatched
    this.store.dispatch(fromActions.loadUsers());
 }
  
}

```

- The Component will use **NgRx selector** `selectUsers` and subscribe to its observable.

```
  
@Component({
 template: `
     <div class="user-container" 
         *ngIf="localUsers$ | async as users">
         <app-user *ngfor="let user of users" 
                    [inputUser]="user">
     </div>
 `
})
export class AppComponent implements OnInit {
  localusers$ = this.store.select(fromSelectors.selectUsers);
  
  constructor(private store: Store<fromApp.AppState>) { }
  
  ngOnInit(): void {
    this.store.dispatch(fromActions.loadUsers());
  }
}

```

- **NgRx Effects** will be listening to the stream of actions dispatched since the latest state change. `loadUsers$` effect is interested in `loadUsers` action dispatched by `AppComponent`. As such, when the component is initialized, the `loadUsers` action is dispatched. The effect reacts to it and subscribes `remoteservice.users$` .

- Once the data is fetched, the `loadUsers$` effect will dispatch `addUsers` action with associated metadata - users. The respective reducer function will transition the state. The latest state will contain recently feteched users.

```
//app.effects.ts
 loadUsers$ = createEffect(
    () => this.action$.pipe(
        ofType(AppActions.loadUsers),
        mergeMap(() => this.remoteService.users$
        .pipe(
            map(users => AppActions.addUsers({ users })),
            catchError(error => {
            return of(error);
            })
        )),
 ));


  
//app.reducer.ts
//addUsers action mapping 
  
const theReducer = createReducer(
  initialState,
  on(AppActions.addUsers, (state, { users }) => ({
    ...state,
    users: [...users]
  }))
  
);

```

- As soon as the data is available, the `localusers$` observable subscription will have users list ready for the component to render.

In contrast with the service-based approach isolating the side-effects using NgRx Effects, the component is not concerned about how the data is loaded. Besides allowing a component to be pure, It also makes testing components easier and increases the chances of reusability.

                    
_If you have come this far, you might also want to know how to install and implement the NgRx Effects in an angular application. I have written a detailed post. **[Click here](https://www.initgrep.com/posts/javascript/angular/handle-side-effects-in-angular-ngrx)** to check it out._