trackBy / track
Without tracking, Angular destroys and recreates every DOM element in a list whenever the data changes. track (and the legacy trackBy) tells Angular how to identify each item so it only touches what actually changed.
Modern Control Flow (@for — Angular 17+)
Section titled “Modern Control Flow (@for — Angular 17+)”track is required in @for — Angular enforces the best practice at compile time:
@for (album of albums; track album.id) { <app-album-card [album]="album" />}track album.id— use a stable, unique propertytrack $index— valid but less efficient (DOM is recycled by position, not identity)
Legacy *ngFor with trackBy
Section titled “Legacy *ngFor with trackBy”For Angular 16 and below, or when still using *ngFor:
@Component({ template: ` <div *ngFor="let album of albums; trackBy: trackById"> {{ album.title }} </div> `})export class AlbumListComponent { trackById(index: number, album: Album): number { return album.id; }}The trackBy function receives (index, item) and must return a stable unique value — usually the item’s ID.
Why It Matters
Section titled “Why It Matters”| Scenario | Without track | With track |
|---|---|---|
| API re-fetches same list | All DOM nodes destroyed and recreated | Nothing changes |
| One item added to end | All nodes recreated | One node inserted |
| One item changes in middle | All nodes recreated | Only that node updated |
| Items reordered | All nodes recreated | Nodes moved in place |
The performance gain is significant for long lists or lists that update frequently.
What to Track
Section titled “What to Track”<!-- ✅ Stable unique ID -->@for (item of items; track item.id) { ... }
<!-- ✅ Compound key if no single unique field -->@for (item of items; track item.type + '-' + item.id) { ... }
<!-- ⚠️ Index only — safe for static lists, poor for dynamic -->@for (item of items; track $index) { ... }
<!-- ❌ Tracking an unstable value defeats the purpose -->@for (item of items; track item) { ... }Key Point
Section titled “Key Point”In modern Angular, @for with track replaces *ngFor + trackBy. The explicit track expression is shorter, inlined, and required — you cannot forget it.

