Complex Changes and Derived State (Angular)
Tags: angular, rxjs, reactive, stateadapt
Published: 2022-07-07 08:41:06

---
title: Complex Changes and Derived State (Angular)
published: true
description: Easily guaranteeing consistency with complex changes and derived state.
tags: angular, rxjs, reactive, stateadapt
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f58xbi7uumnz38y5pxft.png
# zoomed out: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scs44d8fojae69yevked.png
series: Progressive Reactivity in Angular
---

> This series explores how we can keep our code declarative as we adapt our features to progressively higher levels of complexity.

## Level 3: Complex Changes and Derived State

Now that we're using RxJS, we need to keep in mind that RxJS is powerful. It can handle anything, even things that maybe it shouldn't. If we aren't careful, our innocent-looking RxJS pipes will grow and grow until they become a sprawling monster that makes our teammates want to [trash RxJS on Twitter](https://twitter.com/horse_js/status/1438954661575217153).

There isn't a definite line between "should use RxJS" and "this is too complex for RxJS." But these are the signs you're at Level 3 complexity:

- You use a `tap` operator with `console.log` to debug a stream. You need devtools.
- You use `distinctUntilChanged`, `share` or `combineLatest` or other merge operators. You need memoized selectors.
- You wish you could spread objects and arrays in templates to pass to `behaviorSubject$.next(...)`, or you are tempted to create methods to imperatively make those changes from afar. You need a centralized collection of ways your complex object/array can change. RxJS can do this with `scan()`, but it's a lot of boilerplate.

So we want:
- Devtools
- Selectors
- Centralized, declarative state changes

This is starting to sound like a state management library. However, let's not go shopping quite yet. Instead, our goal here will be to invent syntax we think is ideal as we go along, and then only after we've covered all the levels of complexity will we survey the field of state management libraries and decide which ones fit our "progressive reactivity" philosophy most. 

Full disclosure: I created a state management library called [StateAdapt](https://state-adapt.github.io/), and I have been updating its syntax as I've been writing these articles. The actual reason for these articles is to guide my thinking during the process. So, in the end, if you agree with the premises in [the intro of this series](https://dev.to/this-is-angular/progressive-reactivity-in-angular-1d40), StateAdapt will probably have your favorite syntax. However, with only [21 stars on GitHub](https://github.com/state-adapt/state-adapt) as of July 2022, it is definitively in the category of "hobby projects", so I do not recommend using it. And since I can't recommend using it, I will put a serious effort into classifying the various mainstream options at the end of this series, so you know what the best options are for various scenarios, assuming you're interested in achieving progressive reactivity in your own project while avoiding syntactic dead ends.

Alright. Let's think up some syntax that's incrementally more complex than a `BehaviorSubject` that would be perfect for Level 3 complexity.

Let's turn our color picker into a list of color pickers:

![Color Picker—Complex Changes and Derived State](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vwy7t2lzbnvemz8ymz8j.png)

First we'll turn our original color-picker into a component with these inputs and outputs:

```typescript
@Input() color = 'aqua';
@Input() colorName = 'Aqua';
@Output() colorChange = new EventEmitter<string>();
```

Our template doesn't need to change much. Just get rid of the `| async` pipes and do some simple renames. [Here it is in StackBlitz](https://stackblitz.com/edit/angular-ivy-cwnz5p?file=src%2Fapp%2Fcolor-picker.component.ts). 

Now we need a parent component with an `*ngFor` to show the list of colors. It will declare a central `colors` array:

```typescript
export class ColorsComponent {
  colors$ = new BehaviorSubject(['aqua', 'aqua', 'aqua']);
}
```

But how would we change a color? Would we calculate the new state in the template like `colors$.next([$event, colors[1], colors[2])`? This isn't declarative. It's also messy. And it wouldn't be passing minimal data from the template to TypeScript anyway—the minimal data would be `[newColor, index]`. And we don't want to create a callback function that imperatively sets `colors$` (see [Rule 2](https://dev.to/this-is-angular/simple-derived-state-progressive-reactivity-in-angular-48oe)). What we want is a state container (or store) like this:

```typescript
export class ColorsComponent {
  store = createStore(['aqua', 'aqua', 'aqua'], {
    changeColor: (state, [newColor, index]: [string, number]) =>
      state.map((color, i) => i === index ? newColor : color),
  });
}
```

Since we're defining the state and how it can change together, we can have type inference. And it's declarative, so humans can better infer what's going on, too.

What about selectors? The component requires a property of `colorName` as well, so let's make a selector for that derived state. The most convenient would be if we could define it in the same place, under a `selectors` property. I also actually really like NGXS's convention of naming selectors nouns. Let's do that.

And it would be awesome if `createStore` returned a `store` object with all state change functions, as well as observables of every selector bundled together, so we could use it in the component like this:

```html
<app-color-picker
  *ngFor="let color of store.colors$ | async; index as i"
  [color]="color.value"
  [colorName]="color.name"
  (colorChange)="store.changeColor([$event, i])"
></app-color-picker>
```

What about Devtools? If we pass a string to namespace this feature, maybe `createStore` can handle everything behind the scenes.

So, putting it all together, this is the syntax I came up with:

```typescript
export class ColorsComponent {
  store = createStore(['colors', ['aqua', 'aqua', 'aqua']], {
    changeColor: (colors, [newColor, index]: [string, number]) =>
      colors.map((color, i) => i === index ? newColor : color),
    selectors: {
      colors: state => state.map(color => ({
        value: color,
        name: color.charAt(0).toUpperCase() + color.slice(1),
      })),
    },
  });
}
```

This syntax is nice because 

- we don't have to create state management files for state that's still relatively simple. This is incrementally more complex than a BehaviorSubject, and _it's all we need_. 
- It works the same if we need to share with other components—just move it to a service.
- It's 100% declarative for Level 3 complexity. The user events send the minimal data needed to the self-contained store, and all the state change logic is in the same place.

Grouping all of this logic together also enables a pattern that is usually seen as advanced, but should be _a lot_ more common: Reusable state patterns! And that's the next article in this series.