← Back to Articles         
What is ngOnDestroy() in Angular?

What is ngOnDestroy() in Angular?

Published on 30 Sep 2026     6 min read Angular
Component Lifecycle

ngOnDestroy() is an Angular lifecycle hook that runs once just before Angular destroys a component or directive.

It is mainly used to perform cleanup work.

Simple definition: ngOnDestroy() is the component's cleanup method. Angular calls it just before removing that component.


Why Do We Need ngOnDestroy()?

A component may create or start resources while it is active, such as:

  • RxJS subscriptions
  • Timers / intervals
  • Event listeners
  • WebSocket connections
  • Other long-running resources

When the component is removed, some of these resources may need to be stopped or released.

Otherwise, they may continue running unnecessarily and can contribute to:

  • Memory leaks
  • Duplicate event handling
  • Unnecessary processing
  • Unexpected behavior

That's where we use:

ngOnDestroy()

Simple Example

Imagine we have two pages:

Home
  ↓
Products
  ↓
Home

When Angular navigates to the Products page:

ProductsComponent created
        ↓
ngOnInit()

When the user leaves the Products page:

ProductsComponent
        ↓
ngOnDestroy()
        ↓
Component destroyed

So ngOnDestroy() gives us an opportunity to clean up before the component disappears.


Full Simple Sample Program

Let's use a timer because it clearly demonstrates why cleanup matters.

timer.ts

import {
  Component,
  OnDestroy,
  OnInit
} from '@angular/core';

@Component({
  selector: 'app-timer',
  standalone: true,
  template: `
    <h2>Timer Component</h2>

    <p>Seconds: {{ seconds }}</p>
  `
})
export class TimerComponent implements OnInit, OnDestroy {

  seconds = 0;

  private timerId?: ReturnType<typeof setInterval>;

  ngOnInit(): void {

    this.timerId = setInterval(() => {

      this.seconds++;

      console.log('Seconds:', this.seconds);

    }, 1000);
  }

  ngOnDestroy(): void {

    if (this.timerId) {
      clearInterval(this.timerId);
    }

    console.log('Timer component destroyed');
  }
}

Explanation

When the component is created:

ngOnInit()

runs.

Inside it we start:

setInterval(...)

The timer runs every second:

1
2
3
4
5
...

We store its ID:

this.timerId = setInterval(...)

Later, when Angular destroys the component:

ngOnDestroy()

runs.

We stop the timer:

clearInterval(this.timerId);

So the flow is:

TimerComponent created
        ↓
ngOnInit()
        ↓
setInterval()
        ↓
Timer running...
        ↓
User leaves/removes component
        ↓
ngOnDestroy()
        ↓
clearInterval()
        ↓
Timer stopped
        ↓
Component destroyed

Important Real-World Use: RxJS Subscription

A common interview example is cleaning up subscriptions.

Full Example

import {
  Component,
  OnDestroy,
  OnInit
} from '@angular/core';

import {
  interval,
  Subscription
} from 'rxjs';

@Component({
  selector: 'app-user',
  standalone: true,
  template: `
    <h2>User Component</h2>
  `
})
export class UserComponent implements OnInit, OnDestroy {

  private subscription?: Subscription;

  ngOnInit(): void {

    this.subscription = interval(1000)
      .subscribe(value => {

        console.log(value);

      });
  }

  ngOnDestroy(): void {

    this.subscription?.unsubscribe();

    console.log('Subscription cleaned up');
  }
}

Why unsubscribe()?

This creates an RxJS subscription:

this.subscription = interval(1000)
  .subscribe(value => {
    console.log(value);
  });

It continuously emits:

0
1
2
3
4
...

When the component is destroyed, we call:

this.subscription?.unsubscribe();

This stops the subscription.

Component created
      ↓
Subscribe
      ↓
Observable emitting
      ↓
Component destroyed
      ↓
ngOnDestroy()
      ↓
unsubscribe()
      ↓
Subscription stopped

Modern Angular: takeUntilDestroyed()

In modern Angular, you often don't need to manually implement ngOnDestroy() just to unsubscribe from RxJS.

Angular provides utilities such as:

takeUntilDestroyed()

For example:

import {
  Component,
  DestroyRef,
  inject
} from '@angular/core';

import {
  takeUntilDestroyed
} from '@angular/core/rxjs-interop';

import {
  interval
} from 'rxjs';

@Component({
  selector: 'app-user',
  standalone: true,
  template: `
    <h2>User Component</h2>
  `
})
export class UserComponent {

  private destroyRef = inject(DestroyRef);

  constructor() {

    interval(1000)
      .pipe(
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(value => {

        console.log(value);

      });
  }
}

When the component is destroyed, Angular automatically completes the subscription created through this pattern.

So:

Traditional approach
       ↓
ngOnDestroy()
       ↓
unsubscribe()


Modern Angular
       ↓
takeUntilDestroyed()
       ↓
Automatic cleanup

But ngOnDestroy() is still important and useful for general cleanup, not only RxJS.


What Can We Clean Up in ngOnDestroy()?

Typical examples include:

ngOnDestroy()
    │
    ├── Unsubscribe subscriptions
    │
    ├── Clear setInterval()
    │
    ├── Clear setTimeout()
    │
    ├── Remove event listeners
    │
    ├── Close WebSocket connections
    │
    └── Release other resources

Example:

ngOnDestroy(): void {

  this.subscription?.unsubscribe();

  clearInterval(this.timerId);

  this.socket?.close();
}

Advantages

1. Prevents Resource Leaks

Resources that should no longer be active can be released.

2. Stops Unnecessary Processing

For example:

clearInterval(this.timerId);

prevents a timer from continuing after the component is gone.

3. Provides Central Cleanup Location

Cleanup code can be kept in one lifecycle method:

ngOnDestroy()

4. Useful for External Resources

It can clean up resources Angular doesn't automatically manage for you.


Disadvantages / Considerations

ngOnDestroy() itself doesn't have a major disadvantage, but cleanup can be forgotten.

For example, starting:

setInterval(...)

without later calling:

clearInterval(...)

can leave unnecessary work running.

Also, don't assume every Observable subscription always requires manual unsubscription. Some Angular APIs and modern patterns manage subscription lifetimes for you.


Lifecycle Position

ngOnDestroy() is the last lifecycle hook in the component's lifecycle.

A simplified lifecycle sequence:

Component Created
      ↓
ngOnChanges()
      ↓
ngOnInit()
      ↓
ngDoCheck()
      ↓
ngAfterContentInit()
      ↓
ngAfterContentChecked()
      ↓
ngAfterViewInit()
      ↓
ngAfterViewChecked()
      ↓
     ...
      ↓
Component being removed
      ↓
ngOnDestroy()
      ↓
Component Destroyed

ngOnInit() vs ngOnDestroy()

Very easy to remember:

ngOnInit() ngOnDestroy()
Component starting Component ending
Initialization Cleanup
Runs once Runs once
Start resources Stop/release resources
Beginning of active lifecycle End of lifecycle

Think:

ngOnInit()
    ↓
START


ngOnDestroy()
    ↓
CLEAN UP / END

Key Points

  • ngOnDestroy() is an Angular lifecycle hook.
  • It runs once before the component/directive is destroyed.
  • Its primary purpose is cleanup.
  • It can clear timers and intervals.
  • It can remove manually registered event listeners.
  • It can close WebSockets or other external resources.
  • It can unsubscribe from subscriptions when manual cleanup is necessary.
  • Modern Angular also provides DestroyRef and takeUntilDestroyed() for convenient lifecycle-aware cleanup.
  • ngOnDestroy() is essentially the cleanup/end phase of a component's lifecycle.

Interview Questions and Answers

1. What is ngOnDestroy()?

ngOnDestroy() is an Angular lifecycle hook called once just before Angular destroys a component or directive. It is mainly used for cleanup.

2. When is ngOnDestroy() called?

It is called when Angular is about to destroy a component or directive, such as when a routed component is removed during navigation or a conditionally rendered component is removed.

3. What operations are commonly performed in ngOnDestroy()?

Common cleanup operations include:

Unsubscribe subscriptions
Clear timers
Remove event listeners
Close WebSockets
Release resources

4. Why do we unsubscribe in ngOnDestroy()?

For subscriptions that require manual cleanup, unsubscribing prevents them from continuing after the component is destroyed.

5. How many times does ngOnDestroy() execute?

It normally runs once for that component/directive instance, immediately before destruction.

6. What is the difference between ngOnInit() and ngOnDestroy()?

ngOnInit() performs initialization when the component starts.

ngOnDestroy() performs cleanup when the component is about to be destroyed.

7. Do modern Angular applications always need manual unsubscribe() in ngOnDestroy()?

No. Modern Angular provides lifecycle-aware utilities such as takeUntilDestroyed(), and some Angular APIs manage subscription cleanup automatically. Manual cleanup is still required when the resource's lifetime isn't automatically managed.

Easy Memory Trick

ngOnInit()
   ↓
START
   ↓
Component working...
   ↓
ngOnDestroy()
   ↓
CLEAN UP
   ↓
END

One-line Interview Answer

ngOnDestroy() is an Angular lifecycle hook that runs once just before a component or directive is destroyed and is primarily used to clean up resources such as timers, subscriptions, event listeners, and connections.

← Back to Articles