Skip to content
beginner Phase 15 · Performance Optimization and Lazy Loading

Efficient List Rendering with trackBy

Preserve DOM nodes across collection updates.

30m
0 problems
Topic Progress 0%

How trackBy Works

trackBy tells Angular how to match old items to new ones by a stable identity key, preserving DOM nodes across collection updates.

Without trackBy

<!-- Without trackBy, Angular rebuilds all DOM nodes when the array changes -->
<div *ngFor="let item of items">
  {{ item.name }}
</div>

When the array reference changes (even with the same items), Angular destroys and recreates all DOM elements.

With trackBy

@Component({
  selector: 'app-user-list',
  template: `
    <div *ngFor="let user of users; trackBy: trackByUserId">
      {{ user.name }}
    </div>
  `,
})
export class UserListComponent {
  users: User[] = [];

  trackByUserId(index: number, user: User): number {
    return user.id;
  }
}

trackBy with @for

@for (user of users; track user.id) {
  <div>{{ user.name }}</div>
}

Performance Impact

Without trackBy:
  1000 items × rebuild all = 1000 DOM operations

With trackBy:
  1000 items × match by ID = 0 DOM operations (if items unchanged)
  Only changed items are updated

When to Use trackBy

  • Large lists (100+ items)
  • Lists that update frequently
  • Lists with input fields (preserves focus)
  • Real-time data feeds
  • Any list where items are reordered or filtered

trackBy Best Practices

Choosing the right key and using trackBy effectively requires understanding your data.

Choosing a Good Key

// GOOD: Unique, stable ID
trackByUserId(index: number, user: User): number {
  return user.id;
}

// BAD: Index (defeats the purpose)
trackByIndex(index: number, user: User): number {
  return index;
}

// BAD: Non-unique property
trackByName(index: number, user: User): string {
  return user.name; // Names may not be unique
}

trackBy with Input Fields

<div *ngFor="let item of items; trackBy: trackById">
  <input [(ngModel)]="item.value" [id]="'input-' + item.id">
</div>

Without trackBy, typing in an input field would lose focus when the array reference changes. With trackBy, the DOM node is preserved.

trackBy with @for (New Control Flow)

@for (item of items; track trackById(item)) {
  <div>{{ item.name }}</div>
}

@for (item of items; track item.id) {
  <div>{{ item.name }}</div>
}

Common Mistakes

  1. Using index as key — Defeats the purpose of trackBy
  2. Non-unique keys — Causes rendering bugs
  3. Missing trackBy on large lists — Unnecessary DOM churn
  4. Using trackBy with static lists — Unnecessary overhead

Quiz

1. What does trackBy do?

Question 1 options

2. What happens without trackBy when an array reference changes?

Question 2 options

3. What is a good key for trackBy?

Question 3 options

Flashcards

Question

What does trackBy do?

Answer

Matches old items to new ones by stable key. Preserves DOM nodes.

Question

What happens without trackBy?

Answer

Angular destroys and recreates all DOM elements on array change.

Question

Good trackBy key?

Answer

Unique, stable ID (e.g., user.id).

Revision Notes

Key Takeaways

  • 1. trackBy preserves DOM nodes across collection updates
  • 2. Without trackBy, all DOM elements are rebuilt
  • 3. Use unique, stable IDs as keys
  • 4. Essential for large or frequently updated lists

Interview Tips

  • • Explain how trackBy preserves DOM nodes
  • • Be ready to describe when trackBy is necessary
  • • Mention input field focus preservation

Cheat Sheet

trackBy Cheat Sheet

*With ngFor:

<div *ngFor="let item of items; trackBy: trackById">
trackById(index: number, item: Item): number {
  return item.id;
}

With @for:

@for (item of items; track item.id) {

Best key: Unique, stable ID (not index)

Continue Learning