Angular TrackByFunction: The Good, the Obvious, and the Not-So-Obvious

Mehmet Ali Gözbulut
4 min readApr 30, 2019
Interesting gif helps to understand about how trackBy works at Angular

Hello everyone,

In this article, I will try to explain why and how to use the trackBy function with examples.

If you’ve heard of trackBy before, you probably think it’s important just for performance. Yes, it does have a positive effect on performance and the cost of DOM, but this is not the main issue. At a job interview, when you are asked about the trackBy Function, you will not have given an adequate answer if you say” necessary for performance”. In the following example I have a total of 4 records. It wouldn’t be logical to talk about performance for a list of only 4 records. Then, why should we use the trackBy function here? Now let’s examine in detail.

When we need to create a list, we use *ngFor to loop the list elements and create the required list.

*ngFor without trackBy

When a change occurs on the elements in the list (such as adding or deleting new items), the entire list is rendered. As you can see in the example below, we have a list of two records when the page loads. When the “Load More” button is clicked, two more items are added to the existing records. While this is done, the entire list is being refreshed, although no changes have been made to the previous records.

Let’s examine the renewal of the DOM using inspect;

When the button is clicked, you will see re-rendered html elements get highlighted on the right side.

Performance is practically ignorable when there is a list of only 4 entries. Let’s assume we have a list of 10000 entries and that the entire list is rendered again with each change. We can see that rendering the list takes up to a couple of seconds which is too much. However, we normally do not display such a long list at once. Instead, we implement practices such as pagination or virtual lists. Therefore, let’s put aside performance and focus on our main subject.

The real problem here is the re-animation of two already-existing charts on the page. This should not have happened. In other words, we must find a way to animate only the two new charts and avoid animation of others. For this we use the trackBy function. Inside the component class, we should define a trackBy function which returns a unique value. Angular will use this value to generate a diff between lists.

This is not the recommended use. Types are quite important and the type of trackByFn is not specified here. Let’s import TrackByFunction from Angular and use it on our new property.

TrackByFunction import
TrackByFunction Type

We use the trackByFn on the loop in the corresponding component’s html template.

As you can see in the example below, when you click on the “Load More” button, the items in the list are refreshed. Any unchanged element remains untouched. Since it now is easy to understand which elements are added or modified, the user will have an improved experience.

If we examine the end result in developer tools, we now see that only newly added elements are rendered and the existing ones are not.

In conclusion, the trackBy function is used to render elements in a list selectively based on a diff generated by Angular. The obvious gain is of course performance. Yet, when a small list is concerned, this is ignorable. The not-so-obvious benefit is improved user experience through avoiding unintended paints in the browser which could easily be interpreted as errors.

You can review the sample work from the link below.

I hope it was useful. Keep up the good work.

--

--