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
DestroyRefandtakeUntilDestroyed()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.