Component Lifecycle Hooks

From the moment Angular instantiates a Component class to the moment it is removed from the DOM, Angular fires specific logical trigger points called Lifecycle Hooks. Tapping into these hooks allows you to execute precise code at the exact right millisecond of the application's life.

The Constructor vs ngOnInit

Many developers confuse the TypeScript constructor with ngOnInit. The constructor is native Javascript, executed the instant the class is "new'd" up. During this phase, Input properties (Props) have not been evaluated yet by Angular! Therefore, the constructor must strictly ONLY be used for Dependency Injection.

export class MyChildComponent implements OnInit {
  @Input() dataId: number;

  constructor(private api: ApiService) {
    // ❌ DANGEROUS: "dataId" is undefined here! 
    // Data bindings are not evaluated by Angular yet.
  }

  ngOnInit() {
    // ✅ PERFECT: Angular guarantees all @Inputs are ready.
    this.api.fetchInfo(this.dataId).subscribe(...);
  }
}

The Core Hooks Explained

Angular executes hooks in a very specific, strict sequence:

  1. ngOnChanges(): Runs when Angular sets or completely reassigns data-bound input properties. (Runs heavily).
  2. ngOnInit(): Runs exactly once after the first ngOnChanges. This is where all page-load API calls occur!
  3. ngDoCheck(): Runs every time Angular performs a change detection run. Extremely sensitive, use rarely.
  4. ngAfterContentInit(): Runs once after external content has been projected into the component view securely.
  5. ngAfterViewInit(): Runs once after the component's HTML views (and child views) are fully initialized. Useful if you need to manipulate raw HTML elements via @ViewChild safely.
  6. ngOnDestroy(): The final gasp before the component is killed. Critically important for unsubscribing from RxJS Observables to stop Memory Leaks!

Implementation Example

To utilize a hook, you should strictly implement its interface via TypeScript. This guarantees you spelled the hook function name correctly.

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

@Component(...)
export class TimerComponent implements OnInit, OnDestroy {
  timer: any;

  ngOnInit() {
    this.timer = setInterval(() => console.log('Tick'), 1000);
  }

  ngOnDestroy() {
    // If we skip this, the console will print 'Tick' forever, 
    // even after the user navigates to a new page!
    clearInterval(this.timer); 
  }
}

Conclusion

Understanding the lifecycle is critical to preventing bizarre bugs and optimizing memory. As Angular has evolved structurally to v14+, it shifted away from heavy Modules towards Standalone Components, which we dissect in the next chapter.