Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Angular error NG0956 means an @for loop’s track expression made Angular recreate the DOM for every item. If an update replaces list objects with new instances, track a stable, unique property such as todo.id instead of the object itself. Use $index only when the collection’s items and positions stay static.

What NG0956 means

An @for block uses its track expression to associate collection items with their rendered views. As items are added, removed, or moved, Angular uses those keys to determine which DOM views can be reused. The key should represent the logical identity of an item, not merely its current object instance. Angular’s @for API describes the tracking value as the key used to associate array items with DOM views.

NG0956 occurs when the chosen key makes Angular treat every item as new. The list may still display the right data, but Angular throws away and rebuilds its views instead of updating the existing ones. Angular’s NG0956 documentation calls this a very expensive operation, but does not quantify its performance impact.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why tracking an object can recreate every row

Suppose the template tracks each todo object directly:

@for (todo of todos; track todo) {
  <li>{{ todo.task }}</li>
}

This key is the object’s identity. An immutable update that creates replacement objects changes that identity, even if each replacement represents the same todo:

this.todos = this.todos.map(todo => ({ ...todo, done: true }));

After this update, Angular sees new object references. With track todo, it can treat all the rows as new and recreate them, although the logical records remain the same and only a property needs updating.

Fix NG0956 with a stable, unique key

Track a property that uniquely identifies each logical item and remains the same when its object is refreshed or reconstructed. For example, if every todo has a stable, unique id, change the loop to:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
@for (todo of todos; track todo.id) {
  <li>{{ todo.task }}</li>
}

Angular can then match each new object to the existing view for the same todo. Choose a key that meets these checks:

  • It is unique among the items in the collection.
  • It stays stable for the lifetime of the logical item.
  • It is preserved when the data is refreshed or recreated.

If the data has no suitable unique property, decide how the application should identify the same logical record across updates before choosing a tracking expression. An unstable or duplicate key cannot reliably preserve the correct association.

When to use $index

track $index uses an item’s position as its key. Angular documents this as suitable for a collection that remains static. It is not a general fix for NG0956: when items are inserted, removed, or reordered, a position can refer to a different item, so it does not reliably express item identity. For changing collections, use a stable, unique item property instead. See Angular’s @for API guidance.

Why DOM re-creation matters

Rebuilding a row can discard state held by its DOM elements. Angular specifically notes that this can affect focus, text selection, and sites loaded in an iframe. A stable key lets Angular preserve the association between a logical item and its existing view when the item’s data changes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

If the component still uses *ngFor

The older NgFor directive provides a trackBy function for identifying items when object instances change. Angular’s NgFor API says the directive has been deprecated since Angular v20.0 and recommends using @for instead. Check the Angular version used by the project when planning any migration; for current @for code, put the stable key directly in the track expression.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.