Minimizing unnecessary re-renders in AngularJS

Loading

What You’ll Learn

Why unnecessary re-renders happen in AngularJS
How to optimize performance by reducing digest cycles
Best practices to minimize re-renders


1️⃣ Understanding Re-Renders in AngularJS

How Rendering Works in AngularJS?

AngularJS uses the digest cycle to detect changes and update the UI.

  • Every time an event occurs (e.g., API call, user input, timeout), AngularJS checks all bindings and watchers.
  • If there are many watchers, the digest cycle slows down, causing laggy performance.

Why Do Unnecessary Re-Renders Happen?

1️⃣ Too many watchers ($watch, $watchCollection)
2️⃣ Using two-way data binding (ng-model) excessively
3️⃣ Frequent digest cycle triggers ($timeout, $interval, $http)
4️⃣ Unoptimized ng-repeat (large lists)
5️⃣ Not using track by in ng-repeat
6️⃣ Modifying objects inside a digest cycle


2️⃣ Best Practices to Minimize Re-Renders

1. Use One-Time Binding (::)

If data does not change, use one-time binding to remove unnecessary watchers.

<h1>{{ ::user.name }}</h1>
<p>{{ ::user.age }}</p>

This ensures user.name and user.age are evaluated only once.


2. Use track by in ng-repeat

If ng-repeat re-renders too often, AngularJS loses track of items. Use track by to prevent unnecessary re-rendering.

<li ng-repeat="item in items track by item.id">{{ item.name }}</li>

Improves performance by preventing unnecessary DOM updates.


3. Use $watchCollection Instead of $watch for Arrays

If watching arrays, use $watchCollection instead of $watch.

$scope.$watchCollection("items", function(newVal, oldVal) {
console.log("Items changed!");
});

This only watches array length and item changes instead of deep-watching every object property.


4. Use bindOnce in Directives

If a directive displays static content, use bindOnce to prevent re-evaluation.

app.directive("staticInfo", function() {
return {
scope: { data: "=" },
template: "<p>{{ ::data.info }}</p>"
};
});

Prevents unnecessary updates in the directive’s scope.


5. Reduce $digest Scope with $applyAsync

Using $apply() triggers an immediate digest cycle, which is costly. Instead, use $applyAsync(), which batches updates.

$scope.$applyAsync(function() {
$scope.data = newData;
});

Reduces the number of digest cycles.


6. Avoid Unnecessary $http Digest Cycles

If you use $http, disable automatic digest cycles using cache: true or $httpProvider.

app.config(function($httpProvider) {
$httpProvider.useApplyAsync(true);
});

This batches multiple HTTP responses into a single digest cycle.


7. Use bind-once for Large Lists (3rd-Party Solution)

For large lists, use a third-party directive like bindonce.

<li bindonce ng-repeat="item in items">
<span bo-text="item.name"></span>
</li>

Reduces watchers count and improves performance.


8. Optimize ng-show and ng-hide

Problem: ng-show and ng-hide keep elements in the DOM, leading to unnecessary digest cycles.
Solution: Use ng-if instead.

<!-- Bad: Still exists in the DOM -->
<p ng-show="isVisible">Visible text</p>

<!-- Good: Removed from DOM when false -->
<p ng-if="isVisible">Visible text</p>

ng-if removes the element from the DOM, reducing watchers.


3️⃣ When to Use These Optimizations?

ScenarioOptimization to Apply
Static DataUse :: (one-time binding)
Large ListsUse track by in ng-repeat
Watching ArraysUse $watchCollection
Heavy DirectivesUse bindOnce
Frequent API CallsUse $httpProvider.useApplyAsync(true)
DOM PerformancePrefer ng-if over ng-show

Leave a Reply

Your email address will not be published. Required fields are marked *