Early thoughts on Angular with Redux (NgRx)
Tags: angular, typescript, devjournal
Published: 2019-09-01 22:53:27

I've built a number of single page applications in Angular 2, 4, 6, and now 8 (for some reason I tend to like the even-numbered versions).

With 8, I've looked into NgRx and it's a significantly different experience. I want to share some early thoughts as I'm early on in this journey. This will be more about my reactions and less about the code, though I intend to follow-up on this later with a proper tutorial.

# Angular Heroics

My prior experience in Angular revolved around:

- Breaking a page down into individual *components* needed for the UI
- Introducing a *service* for each major piece of application data needed as well as specialized services for things like logging, web communications, showing notifications, etc.
- Wiring things together with *Routes* and *Child Routes*
- Using *Resolvers* to pull data out of *Services* and provide them to *Components* based on the *Route* chosen
- Using *Guards* to prevent invalid use of *Routes*

Most Angular development involved adding Components or Services, then managing subscriptions in `ngOnInit` and `ngOnDestroy` and binding in the template. Dependency Injection made the world go round with easy access to services from components and things stayed simple and usable.

# State strikes back

But things got complicated. In applications with client and server state, the user would make a change and you would then call out to the server to tell the server about the local change. If the server rejected the change, you had to update the UI. Meanwhile, the user could be performing other actions which resulted in other calls. Additionally, some subsequent calls could complete before their earlier calls have returned to the UI.

All of this brews a storm of opportunities for confusing state and communications-related bugs. I've actually resorted to recording video of my network tab mixed with the application UI in order to watch the state of the application and what operations caused the UI to get out of sorts.

# NgRx to the Rescue?

[NgRx, or Reactive Libraries for Angular](https://ngrx.io), brings the Redux pattern of state management to Angular. The Redux pattern is designed as a state-oriented cycle where the UI dispatches actions that a reducer uses to update state, which then is dispatched back to the UI. The key factors here are that state is managed in a centralized spot, and only a handful of reducer actions can modify state, so if a bug occurs in state management, the culprit is easily identifiable.

Beyond that, [the dev tools for Redux](http://extension.remotedev.io/) are fantastic.

![Redux Dev Tools](https://thepracticaldev.s3.amazonaws.com/i/wnsqmdgtotd2l85nffcy.png)

The tools let you look at the history of your application state over time and even jump between different state versions and watch your UI update. This makes the complexities of debugging asynchronous state changes significantly easier.

The downside of this is that instead of dealing with services and methods for the majority of your actions, you have to think in a much more reactive manner, considering event streams, selectors, etc.

For example, to respond to a user event, instead of this:

```ts
  public onBeginShiftClick(): void {
    this.shiftService.beginShift();
  }
```

you would do this:

```ts
  public onBeginShiftClick(): void {
    this.state.dispatch(beginShiftAction());
  }
```

This gets dispatched to a reducer which looks like this:
```ts
const gameReducer = createReducer(GameSimulator.buildDefaultState(),
  on(beginShiftAction, state => GameSimulator.simulate(state)),
  // ....
);

```

Not too hard, I admit.

Where it gets very different is how you get data out of the redux store. Instead of doing something like:

```ts
@Component({
  selector: 'ssit-crew-page',
  templateUrl: './crew-page.component.html',
  styleUrls: ['./crew-page.component.styl']
})
export class CrewPageComponent implements OnInit {

  public crew: CrewMember[];

  constructor(private crewService: CrewService) {
  }

  ngOnInit() {
    this.crew = this.crewService.crew;
  }

}
```

You would instead do:

```ts
@Component({
  selector: 'ssit-crew-page',
  templateUrl: './crew-page.component.html',
  styleUrls: ['./crew-page.component.styl']
})
export class CrewPageComponent implements OnInit {

  public crew$: Observable<CrewMember[]>;

  constructor(private store: GameStateStore) {
  }

  ngOnInit() {
    this.crew$ = this.store.select(this.store.getCrewMembers);
  }

}
```

Because you're now working with an observable stream, you also have to remember to use the async pipe (e.g. `crew | async`) in your template so that the event is auto-subscribed / unsubscribed.

Additionally, you need to implement the selector in the state store:

```ts
const gameSelector = createFeatureSelector<GameState>('game');

export class GameStateStore extends Store<GameState> {
  public readonly getCrewMembers = createSelector(gameSelector, (state: GameState) => state.crew);
  // ...
}

```

# Closing Thoughts

Overall, I'm very early on in my NgRx journey. There are definite advantages and disadvantages so it's not for every project.

## Pros

- Creates a very clear audit trail of state changes
- State changes occur in isolated locations
- No need to subscribe / unsubscribe from events from services (technically, these could be handled with observable streams and pipes, but historically I've subscribed so I'm bundling the new behavior in with NgRx)

## Cons

- More complex than working with individual services
- Selector syntax can be hard to interpret
- Async pipes can be cumbersome and muddle up your templates
- My development speed is much lower, but a lot of that is due to constant learning a different flavor of Angular

I'm going to keep working on NgRx and Angular with [my learning project](https://github.com/IntegerMan/Starship-Tech-Support). I'll keep you posted.