Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 13, 2022 09:17 am GMT

Multi-Store DOM Events (Angular)

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

Level 6: Multi-Store DOM Events

Sometimes multiple stores need to react to a single DOM event. Let's say we have a button in our template that sets all colors in all stores to black. If it weren't for Rule 2, we might write a click handler like this:

  setAllToBlack() {    // `set` is a state change that should come by default with every adapter    this.favoriteStore.set(['black', 'black', 'black']);    this.dislikedStore.set(['black', 'black', 'black']);    this.neutralStore.set(['black', 'black', 'black']);}

But this would log 3 "events" in Devtools back-to-back. Not to mention the total number of imperative statements is 4 now, instead of just the 1 from the template.

To keep our event sources and stores as declarative as possible, we should favor putting logic in state adapters instead of scattered around. It also reduces repetition. So let's add this state change to the adapter:

    setAllToBlack: state => ['black', 'black', 'black'],

Our goal with the button is to push the least amount of data possible to a single place in TypeScript. Since 3 stores need the data, we need to create an independent place to push the event to, and have all stores react to that. We also want to annotate that event source. So let's have something like

  blackout$ = new Source('[Colors] Blackout');

All the stores can connect this source and state change like this:

    setAllToBlack: this.blackout$,

Here's the whole thing with these changes highlighted:

export class ColorsComponent {  adapter = createAdapter<string[]>({ // For type inference    changeColor: (colors, [newColor, index]: [string, number]) =>      colors.map((color, i) => i === index ? newColor : color),+   setAllToBlack: state => ['black', 'black', 'black'],    selectors: {      colors: state => state.map(color => ({        value: color,        name: color.charAt(0).toUpperCase() + color.slice(1),      })),    },  });  initialState = ['loading', 'loading', 'loading'];++ blackout$ = new Source<void>('[Colors] Blackout');  favoriteColors$ = this.colorService.fetch('favorite').pipe(    toSource('[Favorite Colors] Received'),  );  favoriteStore = createStore(    ['colors.favorite', this.initialState, this.adapter], {    set: this.favoriteColors$,+   setAllToBlack: this.blackout$,  });  dislikedColors$ = this.colorService.fetch('disliked').pipe(    toSource('[Disliked Colors] Received'),  );  dislikedStore = createStore(    ['colors.disliked', this.initialState, this.adapter], {    set: this.dislikedColors$,+   setAllToBlack: this.blackout$,  });  neutralColors$ = this.colorService.fetch('neutral').pipe(    toSource('[Neutral Colors] Received'),  );  neutralStore = createStore(    ['colors.neutral', this.initialState, this.adapter], {    set: this.neutralColors$,+   setAllToBlack: this.blackout$,  });}

Here's how it looks:

Color PickerMulti-Store Dom Events

StackBlitz

It is very common for developers to write callback functions so they can dispatch multiple actions for a single event. This is the imperative style and unsurprisingly is often accompanied by forgotten updates and inconsistent state. If you are using NgRx or NGXS, keep your code reactive and dispatch exactly 1 action for each event.


Original Link: https://dev.to/this-is-angular/multi-store-dom-events-angular-a12

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To