A Deep Dive into Angular ngFor Performance Enhancement with TrackBy

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.
\
:::info
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
}
\
Welcome to Billionaire Club Co LLC, your gateway to a brand-new social media experience! Sign up today and dive into over 10,000 fresh daily articles and videos curated just for your enjoyment. Enjoy the ad free experience, unlimited content interactions, and get that coveted blue check verification—all for just $1 a month!
Account Frozen
Your account is frozen. You can still view content but cannot interact with it.
Please go to your settings to update your account status.
Open Profile Settings