Monday, June 5, 2023

Angular Trackby to improve ngFor Performance

Angular Trackby to improve ngFor Performance

Do you utilize ngFor in Angular to iterate over arrays or collections? If that's the case, you might have come across performance issues or unexpected behavior when updating or deleting items. But fret not! Angular offers a practical solution known as trackBy that can greatly enhance the performance and stability of your ngFor loops. Let's delve into it and learn how to effectively use it.


The Challenge

By default, Angular employs the index of each item in an array to track changes in ngFor loops. This implies that if the array's order changes or items are added or removed, Angular will re-render the entire list. Such a scenario can lead to performance bottlenecks, particularly when dealing with large arrays or complex components within the loop.

The following example shows what happens when we refresh the entire list. The App displays the list of names. it has option to add a name, remove a name and refresh the entire name list.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  names = new Array<string>();

  name: string = '';

  ngOnInit() {
    this.Refresh();
  }

  remove(i: number) {
    this.names.splice(i, 1);
  }

  addMovie() {
    this.names.push(this.name);
    this.name = '';
  }

  Refresh() {
    console.log('refresh');
    this.names = ['Manish', 'Rahul', 'Ashish', 'Aditya', 'Rohan'];
  }
}

HTML

<p>App Component</p>
<ul>
    <li *ngFor="let name of names; index as i">
        {{i}}. {{name}} <button (click)="remove(i)">remove</button>
    </li>
</ul>

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

Name : <input type="text" [(ngModel)]="name">
<button (click)="addMovie()">Add Name</button>

You can see from the above example, that Angular renders the entire DOM every time we click on refresh.

The Solution

The trackBy function allows you to provide a unique identifier for each item in your array. Angular utilizes this identifier to track changes instead of relying solely on the index. By doing so, Angular can optimize rendering by reusing DOM elements and updating only the necessary parts of the UI.

How to Use trackBy:

Create a function in your component that takes the index and the item as parameters and returns a unique identifier for that item. This identifier can be a string, number, or any other type that uniquely identifies the item.

trackByFn(index: number, item: any): any {
  return item.id; // Assuming your item has an 'id' property
}

HTML

<div *ngFor="let item of items; trackBy: trackByFn">
  <!-- Your template code here -->
</div>

That's it! Angular will now utilize the identifier returned by the `trackByFn` function to track changes in the `ngFor` loop.

Why It Works

By providing a unique identifier, Angular can accurately determine which items have changed or been added/removed during re-rendering. Consequently, it can update only the affected elements instead of rebuilding the entire list. This approach improves performance by minimizing unnecessary DOM manipulations and rendering cycles.

Best Practices

  1. Use a property with a unique identifier in your items, such as an "id" field.
  2. Ensure that the identifier remains stable and unique throughout the lifecycle of the items.
  3. Avoid using the array index as the identifier, as it can cause issues when items are reordered or removed.

So, the next time you're working with ngFor in Angular, remember to leverage the power of trackBy to optimize your application's performance and provide a seamless user experience! Happy coding!! 😊

No comments:

Post a Comment

^ Scroll to Top