简体   繁体   中英

Angular - ngFor and trackBy with async pipe

I want to use trackBy to improve performance for a long list. The data for this list should be immutable on change and is provided to the template via an async pipe. Altough I'm using the trackBy functionality, the whole list is rerendered everytime I emit a new value. This happens even though the objects inside the array stay the same with the same id .

Component

export class AppComponent implements OnInit {
  data: Observable<any>;

  trackBy(index, item) {
    return item.id;
  }

  ngOnInit() {
    const data = interval(100).pipe(mapTo([
      { id: 1 }, { id: 2 }
    ]))

    this.data = data.pipe(map(events => events.map(event => ({ ...event }))));
  }
}

Template

<div *ngFor="let d of data | async; trackBy: trackBy">{{d}}</div>

Additionally here is a StackBlitz . The div tags are rerendered everytime a new value is send to the ngFor .

As I understand trackBy it should detect that the objects are the same (through the id property), altough the reference changed. Or am I missing something obviously?

You are right, the trackBy can be used to avoid rerendering components when the object does not change. While doing an ngFor on strings or number, it's obvious for Angular, but not on complex objects.

I made a little example to explain the different cases, starting from this Observable :

this.animals = interval(1000)
    .pipe(take(30),
    map(v => ({ id: v} as Animal)),
    scan((acc, curr) => [...acc, curr], []));

The results of this Observable :

 []
 [{id: 0}]
 [{id: 0}, {id: 1}]
 ...

I created a component displaying an input and having a random color everytime it renders, to make the render more obvious.

While using this trackBy fucntion, all the components renders everytime the list changes :

trackBy(index, item) {
    return Math.random();
}

While using this trackBy function, each component renders once only :

trackBy(index, item) {
    return item.id;
}

Here you can find the running example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM