Introduction
When it comes to building efficient and responsive Angular applications, understanding the nuances of data rendering is essential. One of the often-overlooked heroes in this realm is the trackBy
function. In this guide, we'll delve into the world of trackBy
in Angular, demystify its purpose, explore the correct way to use it and learn how it can drastically improve the performance of your application.
What is trackBy?
trackBy
is an Angular directive used to enhance the efficiency of rendering dynamic lists by providing a unique identifier for each item. This identifier allows Angular to track the items efficiently, recognize changes, and update only the relevant parts of the DOM, minimizing unnecessary re-renders.
The Problem It Solves:
When you want to go through a bunch of items in Angular, you typically use something called the ngFor
directive. It's like a tool that helps create a template for each item in your collection.
But, here's the catch: if you ever need to change the data in that collection, like when you get new data from an API, things get tricky. Angular doesn't know which items are added or removed, so it has to do a full reset. It wipes out all the web page pieces connected to your data and builds them again. That's a lot of work, especially if you have a big collection. And as we know that this kind of work with the web page, called DOM manipulation, is expensive.
Let’s see this in action:
So.. what's the solution?
We can help Angular to keep track of added or removed items using trackBy
. So, when changes happen in the collection, Angular can use the unique identifier to figure out which items are new or gone. This means that only the items that have actually changed are created or removed
@Component({
selector: 'my-app',
template: `
<ul>
<li *ngFor="let item of collection; trackBy: trackByFn">{{ item?.name }}</li>
</ul>
<button (click)="addItem()">Add</button>
`,
})
export class App {
collection: { id: number; name: string }[] = [];
constructor() {}
ngOnInit() {
this.collection = [
{ id: 1, name: 'List 1' },
{ id: 2, name: 'List 2' },
{ id: 3, name: 'List 3' },
];
}
addItem() {
this.collection = this.addServer();
}
addServer() {
return [
{ id: 1, name: 'List 1' },
{ id: 2, name: 'List 2' },
{ id: 3, name: 'List 3' },
{ id: 4, name: 'List 4' },
];
}
trackByFn(index: number, element: { id: number; name: string }) {
return index;
}
}
But there is something wrong here 🤔
Wait, wait, wait, wait... hold on. Didn't we just see only the updated list being rendered? So, what's the issue here?
Well... we used the index for tracking in trackBy
, and that's not recommended.
Let's imagine a situation where a new list item is added somewhere in the middle (let's say as the second list item).
And there you have it! The entire list(except for the first list item) is being re-rendered. Why? Because it's comparing the items based on their index, and since each item is mapped to that index, they're all getting updated and causing re-rendering.
So what's the correct way?
We simply require a unique ID (or key) to associate with the items. Here's the revised code:
trackByFn(index: number, element: { id: number; name: string }) {
return element?.id;
}
And Voila! it works😊
Conclusion:
Empowering Angular to accurately track and update items within dynamic lists enhances the responsiveness and efficiency of your user interface. trackBy
might seem small, but its impact is significant.
When applied effectively, trackBy
optimizes performance by minimizing unnecessary DOM manipulations. This translates to smoother user experiences and resource-efficient operation.
So, when working with dynamic lists in Angular, don't underestimate the power of trackBy
. It's a key to improving both user satisfaction and application performance