ngOnInit vs ngOnDestroy in Angular

Introduction

Angular ngOnInit() is responsible for initializing a component after Angular has created it, ngOnDestroy() is used to perform cleanup before the component is destroyed. Understanding when and how to use these lifecycle hooks is essential for building efficient, maintainable, and memory-safe Angular applications.

Many developers use ngOnInit() to fetch data from APIs, initialize forms, or subscribe to Observables. On the other hand, ngOnDestroy() is commonly used to unsubscribe from Observables, remove event listeners, clear timers, and release resources to prevent memory leaks.

What is ngOnInit()?

ngOnInit() is an Angular lifecycle hook that is called once after Angular has initialized the component and set all data-bound properties, including @Input() values.

It belongs to the OnInit interface and is the ideal place to perform component initialization.

Developers commonly use ngOnInit() for:

📖
use ngOnInit():
  • Fetching data from APIs
  • Loading user information
  • Initializing reactive forms
  • Reading route parameters
  • Initializing variables

Unlike the constructor, ngOnInit() is part of Angular’s lifecycle and is specifically designed for initialization logic.

Syntax of ngOnInit()


import { Component, OnInit } from '@angular/core';
@Component({
 selector: 'app-users',
 templateUrl: './users.component.html'
})
export class UsersComponent implements OnInit {
 ngOnInit(): void {
   console.log('Component Initialized');
 }
}

Angular automatically invokes ngOnInit() after creating the component.

What is ngOnDestroy()?

ngOnDestroy() is another Angular lifecycle hook that executes just before Angular destroys a component, directive, or service.

It belongs to the OnDestroy interface and is mainly used to clean up resources that were allocated during the component’s lifetime.

📖
Common uses of ngOnDestroy():
  • Unsubscribing from Observables
  • Clearing timers (setInterval, setTimeout)
  • Removing event listeners
  • Disconnecting WebSocket connections
  • Destroying third-party library instances
  • Releasing memory

Note: Proper use of ngOnDestroy() helps prevent memory leaks and improves application performance.

Syntax of ngOnDestroy()


import { Component, OnDestroy } from '@angular/core';
@Component({
 selector: 'app-users',
 templateUrl: './users.component.html'
})
export class UsersComponent implements OnDestroy {
 ngOnDestroy(): void {
   console.log('Component Destroyed');
 }
}

Angular automatically calls ngOnDestroy() when the component is removed from the DOM.

ngOnInit vs ngOnDestroy

The following table summarizes the key differences between these two lifecycle hooks.

Feature ngOnInit() ngOnDestroy()
Lifecycle Stage Initialization Cleanup
Interface OnInit OnDestroy
Called After component initialization Before component destruction
Execution Count Once Once
Primary Purpose Initialize component Release resources
Common Tasks API calls, forms, subscriptions Unsubscribe, clear timers, remove listeners

Angular Component Lifecycle Order

Understanding where these hooks fit into the Angular lifecycle helps clarify their roles.


Constructor
↓
ngOnChanges()
↓
ngOnInit()
↓
ngDoCheck()
↓
ngAfterContentInit()
↓
ngAfterContentChecked()
↓
ngAfterViewInit()
↓
ngAfterViewChecked()
↓
ngOnDestroy()

Notice that:

  • ngOnInit() runs near the beginning of the lifecycle.
  • ngOnDestroy() is the final lifecycle hook executed before the component is removed.

Example 1: Using ngOnInit()

Suppose you need to load users from a service when a component loads.

User Service


import { Injectable } from '@angular/core';
@Injectable({
 providedIn: 'root'
})
export class UserService {
 getUsers() {
   return ['John', 'Emma', 'David'];
 }
}

Component


import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
 selector: 'app-users',
 templateUrl: './users.component.html'
})
export class UsersComponent implements OnInit {
 users: string[] = [];
 constructor(private userService: UserService) {}
 ngOnInit(): void {
   this.users = this.userService.getUsers();
 }
}

Output

John
Emma
David

The data is loaded as soon as the component initializes.

Example 2: Using ngOnDestroy()

Suppose your component starts a timer.


import { Component, OnInit, OnDestroy} from '@angular/core';
@Component({
 selector: 'app-clock',
 template: `{{time}}`
})
export class ClockComponent implements OnInit, OnDestroy {
 timer: any;
 time = new Date();
 ngOnInit() {
   this.timer = setInterval(() => {
     this.time = new Date();
   }, 1000);
 }
 ngOnDestroy() {
   clearInterval(this.timer);
   console.log('Timer Cleared');
 }
}

Without clearInterval(), the timer would continue running even after the component is destroyed.

Example 3: Unsubscribing from Observables

One of the most common uses of ngOnDestroy() is unsubscribing from Observables.


import { Component, OnInit,OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
export class DashboardComponent implements OnInit, OnDestroy {
 subscription!: Subscription;
 ngOnInit() {
   this.subscription = this.dataService
     .getData()
     .subscribe();
 }
 ngOnDestroy() {
   this.subscription.unsubscribe();
 }
}

This prevents memory leaks caused by long-lived subscriptions.

Real-Life Example

Imagine you’re building a live stock market dashboard.

When the user opens the dashboard:

  • Connect to a WebSocket server.
  • Receive real-time stock prices.
  • Display updated prices every second.

When the user leaves the page:

  • Disconnect from the WebSocket.
  • Stop receiving updates.
  • Free memory.

ngOnInit()


ngOnInit() {
  this.stockService.connect();
}

ngOnDestroy()


ngOnDestroy() {
  this.stockService.disconnect();
}

Another common example is a chat application.

When entering the chat room:

  • Subscribe to incoming messages.
  • Start listening for notifications.

When leaving:

  • Unsubscribe from message streams.
  • Disconnect the socket.
  • Remove notification listeners.

This ensures the application doesn’t continue processing events for components that are no longer visible.

Common Mistakes

1. Forgetting to Unsubscribe

Incorrect:


this.userService.getUsers().subscribe();

No cleanup occurs.

Correct:


this.subscription = this.userService
   .getUsers()
   .subscribe();
ngOnDestroy() {
   this.subscription.unsubscribe();
}

2. Starting Timers Without Clearing Them

Incorrect:


setInterval(() => {
}, 1000);

Correct:


clearInterval(this.timer);
inside ngOnDestroy().

3. Performing Cleanup in ngOnInit()

Avoid writing cleanup logic inside ngOnInit().

Incorrect:


ngOnInit() {
  clearInterval(this.timer);
}

Cleanup belongs in ngOnDestroy().

4. Loading Data in the Constructor

Incorrect:


constructor() {
  this.loadUsers();
}

Correct:


ngOnInit() {
  this.loadUsers();
}

The constructor should be reserved for dependency injection and lightweight object setup.

Best Practices

To make the most of Angular lifecycle hooks, follow these best practices:

📖
Best Practices:
  • Use ngOnInit() for initialization logic only.
  • Use ngOnDestroy() for cleanup tasks.
  • Always unsubscribe from manual Observable subscriptions unless using mechanisms like the async pipe or automatic cleanup utilities.
  • Clear timers and intervals when a component is destroyed.
  • Remove custom event listeners to prevent memory leaks.
  • Implement the OnInit and OnDestroy interfaces for better readability and compile-time checking.

Conclusion

ngOnInit() and ngOnDestroy() are two essential Angular lifecycle hooks that serve opposite but complementary purposes. ngOnInit() is responsible for preparing a component by loading data, initializing forms, reading route parameters, and starting subscriptions. ngOnDestroy(), on the other hand, ensures that the component exits cleanly by unsubscribing from Observables, clearing timers, removing event listeners, and releasing other resources.

A simple way to remember their roles is:

  • ngOnInit() = Set up the component.
  • ngOnDestroy() = Clean up the component.

ngOnInit vs ngOnDestroy – Interview Questions

Q 1: What is ngOnInit?
Ans: ngOnInit is called once after component initialization. It is used to load data and run initialization logic
Q 2: What is ngOnDestroy?
Ans: ngOnDestroy is called before a component is removed. It is used to clean up resources like subscriptions and timers.
Q 3: When should ngOnInit be used instead of constructor?
Ans: Use ngOnInit for data loading and initialization because component inputs are available at this stage.
Q 4: Why is ngOnDestroy important?
Ans: It prevents memory leaks by stopping subscriptions, intervals, and event listeners.
Q 5: Can both hooks be used in one component?
Ans: Yes, ngOnInit handles setup, while ngOnDestroy handles cleanup.

ngOnInit vs ngOnDestroy – Objective Questions (MCQs)

Q1. ngOnInit() runs when:






Q2. ngOnDestroy() runs when:






Q3. ngOnDestroy() is used for:






Q4. ngOnInit is executed:






Q5. ngOnDestroy is useful to:






Related Angular Tutorials