Search code examples
angularmemoizationngrxngrx-store

Angular 2 Redux constantly re-rendering in NgFor


I use NGRX in my project, and have problem with constantly re-rendering of components. The Store produces every time completely new object, if the store data the same, i dont want to re-render my component. I changed change detection of presentation components to ChangeDetectionStrategy.OnPush lodash memoization (_.memoization), but it not works

State of store

export interface CardsState {
    cardsA: CardA[];
    cardsB: CardB[];
    cardsC: CardC[];
}

Then map Store state to structure as this

const entities = [{
 cards: {
  cardsB: [
   {}
  ]
 }
}];

And trying to prevent re-rendering of cardsB items every time when store changing by memoize from lodash

export const memoizeCardBFunc = _.memoize((cardB: CardB): CardB => {
  return _.cloneDeep(cardB);
}, (cardB: CardB) => cardB.entityType + cardB.entityId);

In my Smart Component i have next html

<div *ngFor="let entity of entities | async">
    <div *ngFor="let cardB of entity.cards.cardsB">
        <card-b [cardStateModel]="cardB"></card-b>
    </div>
</div>

To the my surprise it correctly works with one ngFor, but if i have two ngFor it is not works!

<div *ngFor="let cardB of entity.cards.cardsB">
    <card-b [cardStateModel]="cardB"></card-b>
</div>

I have already spended 2 days for it, and it is killing me, please, help!

I am not native English speaker, sorry for mistakes.

Thanks!


Solution

  • If you have:

    <div *ngFor="let outer of outers">
        <div *ngFor="let inner of outer.inners">
           {{ inner }}
        </div>
    </div>
    

    Then if outer changes at some point, the inner ngFor will re-render, which is why you see the alerts from ngOnInit. But if you add a trackBy to your outer ngFor, and it recognizes it as the same element, then you can avoid the inner list re-rendering, which is your current problem.

    The inner trackBy only preserves the inner elements and prevents those from being re-created. The outer trackBy preserves the outer elements, which allows the inner elements the chance to be preserved too.