0

In the ngrx store when i do select to the state and then use the object in the template multiple time with async pipe. Does this hurt preformance?

This is the code i am using :

Constructor :

this.tabs = this.store.select(s => { return s.lobby.lobbyTabs});

Template :

<div *ngIf="(tabs | async) && (tabs | async).length >0 && (tabs | async)[tabIndex].TabPositions && (tabs | async)[tabIndex].TabPositions.length > 0 && (tabs | async)[tabIndex].themeId ==1">

<div *ngFor="let i of createNumArray((tabs | async)[tabIndex].TabPositions.length)" class="column">
              <app-ticket [ticket]='rooms[(tabs | async)[tabIndex].TabPositions[i-1].Id]' [themeId]='(tabs | async)[tabIndex].themeId'
                [lastLobbyTimestamp]='(lastLobbyTimestamp | async)'></app-ticket>
            </div>

Is there a better way to work with the async pipe?

Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
Haniel Bitton
  • 84
  • 1
  • 7

1 Answers1

3

Having several async's is ok, they are pretty performant. However, you could eliminate several of those async calls by putting the logic in your selectors instead.

Instead of selecting just the tab data and then putting logic in your ngIf, move all that logic into a selector:

this.showAppTickets = this.store
    .select(state => state.lobby.lobbyTabs)
    .map(tabs => {
        return tabs && tabs.length && tabs[tabIndex] &&
        tabs[tabIndex].tabPositions &&
        tabs[tabIndex].tabPositions.length > 0 && 
        tabs[tabIndex].themeId === 1})

That lets you use less asyncs in your template:

<div *ngIf='showAppTickets | async'>

You can do the same thing with the source for your ngFor. I usually map my collection into intermediate objects so I only use the async pipe in the ngFor, not in the inputs for the components im looping over.

<div *ngFor='let item of items | async'>
    <app-ticket 
        [ticket]='item.ticket' 
        [themeId]='item.themeId'
        [lastLobbyTimestamp]='item.lastTimeStamp'>
    </app-ticket>
</div>

If you use the selectors / rxjs operators in your component class appropriately, you'll only need two async pipes in your template. This makes your template easier to read, more performant, and more testable

adharris
  • 3,591
  • 1
  • 21
  • 18
  • It's important to note that `showAppTickets` won't get any updates pushed from the store unless you re-run the function sets that local observable. Instead you get make `showAppTickets` a getter: `get showAppTickets() { return this.store.pipe(select(......)); }` – Alex White May 31 '18 at 00:02