Since recently, the Angular styleguide-lint-extender "Codelyzer" is throwing warnings when you do not have a trackBy-function implemented on every *ngFor. I am wondering why this is considered an issue at all.
trackByFn(index, item) { return index;} // or item.id
. If I switched from index to item.id, how would this make my app faster? when it comes to array insertions or deletions, index is the most straightforward thing that matters. Why should the [ngFor]-directive compare object identity values instead?_trackByFn
. So I assume, a return index
-trackBy is the default configuration anyway? Then why is it considered a good practice to implement it explicitly?Now personally, I do have a big collection (array) in my app, and it lies in a redux store. It can only be replaced by an empty array or new items can get added to it, eg:
return {...state, myArray: [...state.myArray, ...newItems]}
),
but never moved or deleted. Would it make sense for me to track by item.id
instead of index
? Should I really implement a return index;
-function in every component with an *ngFor?
Angular came up with the trackBy directive, which is optionally passed into ngFor to help identify unique items in our arrays. TrackBy and ngFor together allow Angular to detect the specific node element that needs to change or be added instead of rebuilding the whole array.
The use of trackBy it's a performance optimization and is usually not needed by default, it's in principle only needed if running into performance issues.
Angular Trackby option improves the Performance of the ngFor if the collection has a large no of items and keeps changing. Learn why we need it and how to use it to improve the performance of the ngFor .
The angular ngFor trackBy is used to improve the performance of an angular application. At the. end of this blog, you will understand how to use ngFor trackBy and when to use the ngFor trackBy in your angular application.
*ngFor
tracks the items by object identity and tries to avoid re-render of elements when the iterated array is updated for items in the array that where in the array already before the update.
If the array contains primitive values (string, boolean, number), then *ngFor
can't identify them after they were modified.
An *ngFor
over a list of strings like
items = ['foo', 'bar', 'baz'];
<input *ngFor="let item of items" [(ngModel)]="item">
would cause weired behavior when the value is modified in the rendered <input>
because after each keyboard input the value would change and *ngFor
would loose track where the item was rendered before and therefore remove the input for the value before the change and add it for the value after the change. This causes the input to lose focus and can cause the input to change position.
To fix this you can instruct *ngFor
to track by index instead of by identity.
See also
Also for objects it can be useful, for example if you want *ngFor
to track items by an id
property.
This is useful for example if immutable values are used and an item of the list was modified - which means replaced by a new object instance with the same value for the id
property, but some other properties changed. Instructing *ngFor
to track by id
doesn't cause the item to be removed and re-added to the DOM.
*ngFor
not properly recognizing modified items would also cause animations like shown in this Plunker example (from How can I animate *ngFor in angular 2?) to break (animated too often).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With