Improving Angular *ngFor Performance With trackBy

Angular uses many conditional structural directives such *ngIf, ngSwitch, ngSwitchCase etc. One of the most used conditional directives used is *ngFor. Basically, this directive is used for iterating an array or an object and display it in the view(HTML). The * character before ngFor creates a parent template.

In this blog, we shall see about how this ngFor is used for iterating and displaying values in the view. And also we shall see how we can improve the performance of *ngFor using trackBy.

How to iterate using *ngFor?

Let’s take a small example of how we can use *ngFor in our respective angular application.

app.component.ts

  blogs = [
    {name: 'nullablereference'},
    {name: 'efficientuser'},
    {name: 'debugmode'}
  ]

app.component.html

<div class="container">
  <ul>
    <li *ngFor="let blog of blogs">
      {{blog.name}}
    </li>
  </ul>
</div>

So we have an array of objects called blogs and we are just iterating through this array using *ngFor and printing the respective blog name. So let’s add some code.

app.component.ts

  refreshNames(){
    this.blogs = [
      {name: 'nullablereference'},
      {name: 'efficientuser'},
      {name: 'debugmode'}
    ]
  }

We have added a refresh functionality where it will refresh the respective blog list.

app.component.html

<button (click)="refreshNames()">Refresh</button>

And also in the view, we have added a button called Refresh where it will call the respective refresh function in the typescript. You know in the view, it looks fine and the array gets refreshed very quickly. So Everything works fine right, then why should you bother?

IF IT WORKS FINE,

MAKE IT WORK BETTER!

If you analyze the DOM, whenever you click that button, the whole div structure will be entirely re-rendered which is not good. If you have many elements in the array it may lead you to performance issues.

In the above gif, you can see when I click the Refresh button the whole list DOM gets re-rendered.

How to solve this?

So it happens because *ngFor doesn’t store the state of the respective object. And so if the refresh button is clicked, the whole DOM gets re-rendered. So to avoid this issue we can make use of trackBy.

app.component.html

<div class="container">
  <ul>
    <li *ngFor="let blog of blogs; trackBy: trackByFuntion">
      {{blog.name}}
    </li>
  </ul>
</div>

app.component.ts

 trackByFuntion(index, item) {
    return index;
  }

Now we have added a trackBy in the ngFor and now if you press the refresh button, you won’t see the re-render of the DOM since it already stores the loaded object.

Here is a stackblitz demo that demonstrates the trackBy Function.

Stackblitz link => https://bit.ly/2DYv0L7

Conclusion

From the next time, analyze the things that you do and try to get deeper into it. And also change your mind from “If its working fine, don’t touch it” to “If it working fine, make it work better“. By doing this, you should be able to improve the performance of your application like the one we have solved it now.

trackBy will be very useful when you have a lot elements in your respective array.

In our next blog, we will explore about RxJS and also we will see an detailed difference between Subject and Behavior Subject.

Happy Coding!

Cheers! 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: