I was recently developing a chat application with Angular 7. That app had a chat room feature which renders several messages per minute. In the beginning all looked nice and fine but eventually, when the number of messages was growing it got extremely slow.

That’s when I started looking more into how angular ngFor works under the hood and eventually found out what has gone wrong.

If a list consists of objects other than primitive type values, when the list is modified ( added new object to list, removed one from the list, modifying an existing one) Angular checks reference of all objects in the array. If object reference has changed, that object would get re-rendered. This could lead to major performance issues as the application grows.

Object reference is where the object is created in memory. If someone re-create same type of object using same values, then both objects look same but they are created in different locations of memory, then there references are different

Following is my controller code for the chat room. When a message is added ( when addNewRandomMessage function is called) it re-populates the chat message list with new instances of existing chat messages and adds a new message object at the end.

So, every time a new chat element is added to the list, object references are getting changed in the whole list. In this scenario, this can be avoided easily, But there are some cases where there is no other option ( my actual chat room code was way complex than this and there was no way to prevent the object initialization)

Template HTML code of that controller looks like following,

After rendering this, it looks like following

This shows the output of Chrome developer tools. It clearly shows that the whole list is re-rendering every time a new message is added to the list. Then this was the time to find out a way to overcome this unnecessary rendering.

Then I found ‘trackBy’ functionality in ngFor

As per the name, It is a way to track elements in Angular ngFor array. Using this feature, a developer can define a way to uniquely identify elements in a list.

The developer has to define a function in the controller which would get the index of an array element and element itself as parameters and returns a unique identifier for the element.

When the array is updated and the unique id is not changed by that update, then that element won’t get re-rendered.

Following code shows how to add trackBy to ngFor in the template,

And in the controller code, define the relevant trackBy function,

After adding trackBy, the final output looks like following,

Only the newly added element is rendered and the rest remains unchanged. So the problem is solved 😃

Try using trackBy in your next project to avoid unnecessary rendering and increase angular app performance !!!

Find the full code of this example in GitHub,