Inaccurate trackBy section
mgechev opened this issue · 7 comments
Looking at the DefaultIterableDiffer
, it uses trackByIdentity
function in case the trackBy
argument is not provided. This makes the trackBy
section inaccurate since Angular is never going to destroy the entire list in case trackBy
is not provided to the differ.
This change might has been introduced in recent releases.
@tytskyi would you verify so that we can correct the content?
Hi @mgechev i confirm that it does not destroy the whole list.
Further investigation gives me next results:
You are right it does track by identity by default.
-
No track-by provided - Developer updates item of collection inplace:
-- No dom nodes are removed. Content of target node is changed. -
No track-by provided - Developer changes item by creating new object of the same type (breaking reference), other items remains the same:
-- Target dom node is removed and new node is created and inserted on its place. -
Track-by provided - Developer changes item by creating new object of the same type (breaking reference), other items remains the same:
-- No dom nodes are removed. Content of target node is changed.
Which means that wording is too dramatic and must be changed from statement that the whole list is re-rendered - to something like "giving the hint to Angular how to identify items". And the bigger performance win is achieved when reloading big list of search results from server - when track-by provided dom nodes would be re-used for matching items.
Let's consider this a draft. I think the structure is ok, however i am not sure in language - i will need to refine it tomorrow, plus i am open for suggestions:
Use trackBy
option for *ngFor
directive
The *ngFor
directive is used for rendering a collection. By default *ngFor
identifies object uniqueness by reference.
Which means when developer breaks reference to object during updating item's content Angular treats it as removal of the old object and addition of the new object. This effects in destroying old DOM node in the list and adding new DOM node on its place.
Developer can provide a hint for angular how to identify object uniqueness: custom tracking function as trackBy
option for the *ngFor
directive. Tracking function takes two arguments: index
and item
. Angular uses the value returned from tracking function to track items identity. It is very common to use ID of the particular record as the unique key.
Even bigger performance save would be if trackBy
is implemented for some collection which can be reloaded from the server (for example search results). Where each fetch will return collection of freshly new objects.
Example
@Component({
selector: 'yt-feed',
template: `
<h1>Your video feed</h1>
<yt-player *ngFor="let video of feed; trackBy: trackById" [video]="video"></yt-player>
`
})
export class YtFeedComponent {
feed = [
{
id: 3849, // note "id" field, we refer to it in "trackById" function
title: "Angular in 60 minutes",
url: "http://youtube.com/ng2-in-60-min",
likes: "29345"
},
// ...
];
trackById(index, item) {
return item.id;
}
}
@tytskyi I like it, maybe we can drop:
Even bigger performance save would be if trackBy is implemented for some collection which can be reloaded from the server (for example search results). Where each fetch will return collection of freshly new objects.
@mgechev yes i am happy to drop it, plus i want to fix definite article
custom tracking function as the trackBy option`
If you are happy with this patch i will send PR in 1 hour
Sounds good to me!