All topics
Performancebeginner

trackBy for List Rendering

Explain how trackBy (and @for's mandatory track) prevents unnecessary DOM node recreation when rendering lists.

Without a tracking mechanism, when the array bound to a list renders a new set of objects (even if many represent the exact same underlying data), Angular's default behavior falls back to comparing by object identity, and if the array reference itself changed (a very common pattern, especially with immutable state updates), Angular has no way to know that "item at index 3" in the new array is conceptually the same as "item at index 3" in the old array unless you tell it how to identify sameness — which is exactly what trackBy (for *ngFor) or the mandatory track expression (for @for) provides.

Without trackBy, updating a seating chart means tearing down and rebuilding every chair in the room from scratch even if only one guest left; with trackBy, each chair has a nameplate, so the room can simply remove one chair and leave everyone else's exactly where they were sitting.

Key Concepts

1
Without it, Angular's worst-case fallback is destroying and recreating every DOM node for every item on every list update, which is expensive (DOM operations are costly) and destructive to any local DOM state — losing input focus, resetting scroll position within a row, discarding CSS transition/animation state, and forcing child components within each row to be torn down and reconstructed rather than simply updated.
2
Supplying a trackBy function (returning a stable identifier, typically an item's id, given the index and item) tells Angular exactly how to match old items to new ones by identity rather than by object reference or array position, so Angular can correctly compute a minimal diff — creating DOM nodes only for genuinely new items, removing nodes only for genuinely removed items, and reordering existing nodes in place rather than recreating them, for items that persist across the update.
trackBy
3
As covered under the New Control Flow with the @for Block topic, this optimization is no longer optional in modern Angular — @for requires a track expression to even compile, which reflects Angular's own official position that skipping this optimization was common enough, and costly enough, to warrant making it a compiler-enforced requirement rather than a discoverable-if-you-read-the-docs best practice.
@fortrack