Skip to main content
Angular Basics
CHAPTER 15 Beginner

Angular Lifecycle Hooks

Updated: May 18, 2026
5 min read

# CHAPTER 15

Angular Lifecycle Hooks

1. Chapter Introduction

Every Angular component has a lifecycle — a series of stages from creation to destruction. Angular calls specific hook methods at each stage, allowing developers to run custom code at precisely the right moment. Understanding these hooks is critical for loading data correctly, responding to input changes, and preventing memory leaks.

2. Learning Objectives

  • Understand the Angular component lifecycle sequence.
  • Use ngOnInit for initialization logic.
  • Use ngOnChanges to react to @Input changes.
  • Use ngOnDestroy for cleanup (unsubscribing Observables).
  • Implement other hooks: ngAfterViewInit, ngDoCheck.

3. The Lifecycle Sequence

text
123456789101112131415
Component Created
      ↓
  ngOnChanges()     ← Fires when @Input property changes
      ↓
  ngOnInit()        ← Fires ONCE after component is initialized
      ↓
  ngDoCheck()       ← Fires on every change detection cycle
      ↓
  ngAfterViewInit() ← Fires after component's view (template) is rendered
      ↓
  [On each @Input change] → ngOnChanges() again
      ↓
Component Destroyed
      ↓
  ngOnDestroy()     ← Fires just before component is removed from DOM

4. ngOnInit — The Most Important Hook

Use ngOnInit to fetch data, initialize subscriptions, and set up the component. Never put heavy logic in the constructor — the constructor should only receive injected services.
typescript
123456789101112131415161718
import { Component, OnInit } from '@angular/core';
import { UserService } from '../user.service';

@Component({ selector: 'app-user-list', templateUrl: './user-list.component.html' })
export class UserListComponent implements OnInit {
  users: any[] = [];

  constructor(private userService: UserService) {
    // Good: Only dependency injection here
  }

  ngOnInit(): void {
    // Good: Data fetching and initialization here
    this.userService.getUsers().subscribe(users => {
      this.users = users;
    });
  }
}

5. ngOnChanges — Reacting to @Input Changes

typescript
1234567891011121314
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({ selector: &#039;app-user-card&#039;, template: &#039;<p>{{ user?.name }}</p>&#039; })
export class UserCardComponent implements OnChanges {
  @Input() user: any;

  ngOnChanges(changes: SimpleChanges): void {
    if (changes[&#039;user&#039;]) {
      const previousUser = changes[&#039;user&#039;].previousValue;
      const currentUser = changes[&#039;user&#039;].currentValue;
      console.log(&#039;User changed from&#039;, previousUser, &#039;to&#039;, currentUser);
    }
  }
}

6. ngOnDestroy — Preventing Memory Leaks

When a component is removed, any active Observable subscriptions continue running in memory unless explicitly cancelled. This is a memory leak!
typescript
1234567891011121314151617181920
import { Component, OnInit, OnDestroy } from &#039;@angular/core&#039;;
import { Subscription, interval } from &#039;rxjs&#039;;

@Component({ selector: &#039;app-timer&#039;, template: &#039;<p>Timer: {{ count }}</p>&#039; })
export class TimerComponent implements OnInit, OnDestroy {
  count: number = 0;
  private timerSub!: Subscription;

  ngOnInit(): void {
    this.timerSub = interval(1000).subscribe(() => {
      this.count++;
    });
  }

  ngOnDestroy(): void {
    // Critical! Unsubscribe when component is destroyed
    this.timerSub.unsubscribe();
    console.log(&#039;TimerComponent destroyed, subscription cleaned up.&#039;);
  }
}

7. ngAfterViewInit — After View Renders

typescript
12345678910
import { AfterViewInit, ViewChild, ElementRef } from &#039;@angular/core&#039;;

export class FocusInputComponent implements AfterViewInit {
  @ViewChild(&#039;searchInput&#039;) searchInput!: ElementRef;

  ngAfterViewInit(): void {
    // The template is fully rendered here, safe to access DOM elements
    this.searchInput.nativeElement.focus();
  }
}

8. Common Mistakes

  • HTTP calls in the constructor: The Angular DI system hasn't fully initialized when the constructor runs. Always put initialization logic in ngOnInit.
  • Not unsubscribing: The most common Angular memory leak. If you subscribe in ngOnInit, always unsubscribe in ngOnDestroy (or use the async pipe which handles this automatically).

9. Best Practice: The takeUntilDestroyed Operator (Angular 16+)

typescript
12345678910
import { takeUntilDestroyed } from &#039;@angular/core/rxjs-interop&#039;;

export class MyComponent {
  constructor(private userService: UserService) {
    // Automatically unsubscribes when component is destroyed!
    this.userService.getUsers()
      .pipe(takeUntilDestroyed())
      .subscribe(users => this.users = users);
  }
}

10. MCQs with Answers

Question 1

Which lifecycle hook fires ONCE after a component's properties have been initialized?

Question 2

Which hook should you use to detect and respond to changes in @Input properties?

Question 3

Which hook is the correct place to unsubscribe from Observables to prevent memory leaks?

Question 4

Why is it bad practice to make HTTP calls inside the constructor?

Question 5

What does ngAfterViewInit guarantee?

Question 6

What causes a memory leak in Angular?

Question 7

What does the SimpleChanges object contain in ngOnChanges?

Question 8

In what order do the first three lifecycle hooks execute?

Question 9

What modern Angular operator automatically handles unsubscription?

Question 10

What interface should a component implement if it uses ngOnInit?

11. Interview Questions

  • Q: What is the difference between the constructor and ngOnInit?
  • Q: How do you prevent memory leaks caused by Observable subscriptions in Angular?

12. Summary

Angular's lifecycle hooks give developers precise control over a component's existence. ngOnInit is the correct place for initialization work, ngOnChanges responds to parent data updates, and ngOnDestroy is the cleanup guardian preventing memory leaks. Mastering these hooks is a sign of an experienced Angular developer.

13. Next Chapter Recommendation

Every Angular component belongs to a module. In Chapter 16: Angular Modules, we explore NgModules, feature modules, shared modules, and how modules control what gets imported and exported in your application.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·