paint-brush
A Deep Dive into Angular ngFor Performance Enhancement with TrackByby@saravananbsctech10
163 reads

A Deep Dive into Angular ngFor Performance Enhancement with TrackBy

by May 23rd, 2024
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

When you're working with an array of primitive values (like numbers or strings), Angular's ngFor directive works pretty straightforwardly.
featured image - A Deep Dive into Angular ngFor Performance Enhancement with TrackBy
undefined HackerNoon profile picture

Why trackBy?

When you're working with an array of primitive values (like numbers or strings), Angular's ngFor directive works pretty straightforwardly. It keeps track of each item's position in the array. So if the array changes – items get added, removed, or updated – Angular knows exactly which parts of the list need updating because it's based on their position.


However, when you're using an array of objects (as in your second example), Angular needs more information to track changes efficiently. By default, Angular tracks objects in the array by their identity. When you have an array of objects bound to a template using *ngFor, any change to the array triggers Angular's change detection mechanism to update the corresponding DOM elements. However, Angular tries to optimize this process by comparing the objects in the array by reference.


When you add an object in the middle of the array, Angular's default change detection algorithm doesn't have a way to know where exactly the change occurred. It simply sees that the array reference has changed, so it assumes that every item in the array might have changed and updates all corresponding DOM elements.


By using a trackBy function, Angular can more efficiently determine which items have been added, removed, or moved within the array, and only update the corresponding DOM elements for those specific items. This can significantly reduce the amount of DOM manipulation required and improve the overall performance of your application.


Add the below code in your angular project. Then in the browser inspect and see the how dom updates it.

Before using trackBy:

HTML:

<div>
 <button (click)="refresh()">Refresh</button>
  <ul>
   <li *ngFor="let user of users">{{ user.name }}</li>
  </ul>
</div>

TS:

users = [
    { id: 1, name: 'Steve' },
    { id: 2, name: 'John' },
    { id: 3, name: 'Carol' }
];

refresh() {
  this.users = [
    { id: 1, name: 'Steve' },
    { id: 2, name: 'John' },
    { id: 3, name: 'Sarah' },
    { id: 4, name: 'Carol' }, 
    { id: 5, name: 'Mike' }
  ];
}

After using trackBy:

HTML:

<div>
 <button (click)="refresh()">Refresh</button>
  <ul>
   <li *ngFor="let user of users; trackBy: trackById">{{ user.name }}</li>
  </ul>
</div>

TS:

users: { id: number, name: string } = [
    { id: 1, name: 'Steve' },
    { id: 2, name: 'John' },
    { id: 3, name: 'Carol' }
];

refresh() {
  this.users = [
    { id: 1, name: 'Steve' },
    { id: 2, name: 'John' },
    { id: 3, name: 'Sarah' },
    { id: 4, name: 'Carol' }, 
    { id: 5, name: 'Mike' }
  ];
}

// trackBy function first argument is always an index
trackById(index: number, user: { id: number, name: string }): number {
   return item.id; // Unique identifier for each item
}