DEV Community

Cover image for Angular’s ngDoCheck: The Powerful but Dangerous Lifecycle Hook
Ayush Maurya
Ayush Maurya

Posted on

Angular’s ngDoCheck: The Powerful but Dangerous Lifecycle Hook

ngDoCheck is underrated — but dangerous if misused.

This lifecycle hook runs every time Angular performs change detection, regardless of whether the @Input() properties have changed or not.

Since it gets called frequently, putting heavy logic inside ngDoCheck can make your app laggy or unresponsive. But in some scenarios, it's incredibly useful.

When to Use ngDoCheck

1. Detecting deep changes in Objects or Arrays

Angular performs a shallow comparison on @Input() properties. So, if an object or array is mutated, ngOnChanges() won’t fire.

What do most devs do here? They often work around it by cloning the array or object and reassigning it — or worse, serializing it with JSON.stringify() and parsing it back. Gross.

Instead, use ngDoCheck to manually detect changes in such cases.

2. Tracking internal state changes
ngDoCheck also triggers when any internal value of the component changes — not just @Input() bindings. This makes it useful for watching component-local state too.

When You Should Use ngDoCheck

  1. Angular’s default change detection misses what you actually care about.
  2. You’re dealing with mutable data, and ngOnChanges() isn’t firing.
  3. You need fine-grained control over reactivity.

Real-World Example

Say you have a chat UI. The parent component pushes messages into an existing array, but doesn’t create a new array. Angular won’t detect this change.

@Component({
  selector: 'app-chat',
  template: `<ul><li *ngFor="let msg of messages">{{ msg }}</li></ul>`,
})
export class ChatComponent implements DoCheck {
  @Input() messages: string[] = [];
  private prevLength = 0;
  ngDoCheck() {
    if (this.messages.length !== this.prevLength) {
      console.log('New messages received');
      this.prevLength = this.messages.length;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

This lets you detect new messages even if the array reference didn’t change.

ngDoCheck() + IterableDiffers / KeyValueDiffers

Angular also gives you tools for detecting changes in arrays or objects.

Example using IterableDiffers:

constructor(private differs: IterableDiffers) {}
private differ = this.differs.find([]).create();

ngDoCheck() {
  const changes = this.differ.diff(this.myArray);
  if (changes) {
    console.log('Array changed!');
  }
}
Enter fullscreen mode Exit fullscreen mode

This is cleaner and avoids manual comparison logic.

When to Avoid ngDoCheck

  1. You’re using immutable data (e.g., @Input() user is reassigned, not mutated) — just use ngOnChanges()
  2. You only need to track a simple @Input() value
  3. You’re worried about performance, and this isn’t absolutely necessary

As Angular’s documentation clearly states:

“Typically, you should not use both ngDoCheck and ngOnChanges to respond to changes on the same input.”

TL;DR

Use ngDoCheck only when:

  1. You’re working with mutable data
  2. Angular’s change detection isn’t enough
  3. You know what you’re doing and you really need it
  4. Otherwise, stick with ngOnChanges().

Top comments (0)