Lifecycle Hooks
Angular components have a lifecycle: they are created, rendered, updated, and eventually destroyed. Angular provides lifecycle hooks — methods you implement on the component class — that run at specific points in this process.
The most important hooks
Section titled “The most important hooks”Angular provides a handful of lifecycle hooks. In practice, you will use two almost exclusively:
| Hook | When it runs |
|---|---|
ngOnInit | Once, after Angular has set all @Input() properties |
ngOnDestroy | Once, just before Angular removes the component from the DOM |
There are others (ngOnChanges, ngAfterViewInit, etc.) but ngOnInit and ngOnDestroy cover the vast majority of real use cases.
ngOnInit — running code when a component loads
Section titled “ngOnInit — running code when a component loads”ngOnInit is the right place to fetch data and run any setup logic. It fires after all @Input() values are set, which means you can safely use input values inside it.
In CinemaVault, Home fetches trending and popular movies when it loads:
import { Component, OnInit } from '@angular/core';import { MovieService } from '../../services/movie.service';import { Movie } from '../../models/movie.model';
@Component({ selector: 'app-home', templateUrl: './home.html', styleUrl: './home.css'})export class Home implements OnInit { trending: Movie[] = []; popular: Movie[] = []; loading = true;
constructor(private movieService: MovieService) {}
ngOnInit(): void { this.movieService.getTrending().subscribe(movies => { this.trending = movies; }); this.movieService.getPopular().subscribe(movies => { this.popular = movies; this.loading = false; }); }}Notice implements OnInit. This is a TypeScript interface — it ensures your class has the correct ngOnInit signature. Angular does not require it (it uses duck typing), but it helps with type checking and makes intent clear.
Why not the constructor?
Section titled “Why not the constructor?”You might wonder: why not fetch data in the constructor? Two reasons:
@Input()values are not set yet when the constructor runs. If you usethis.movieinside a constructor, it will beundefined.- Constructors should be simple. Angular uses the constructor for dependency injection. Putting side effects (API calls, subscriptions) in the constructor makes testing harder and violates the principle of minimal constructors.
Reserve the constructor for injecting services. Use ngOnInit for everything else.
ngOnDestroy — cleanup
Section titled “ngOnDestroy — cleanup”ngOnDestroy runs just before Angular removes the component. Use it to cancel subscriptions, clear timers, and release any resources the component holds.
import { Component, OnInit, OnDestroy } from '@angular/core';import { Subscription } from 'rxjs';
@Component({ /* ... */ })export class Browse implements OnInit, OnDestroy { private sub?: Subscription;
ngOnInit(): void { this.sub = this.formService.changes$.subscribe(handleChange); }
ngOnDestroy(): void { this.sub?.unsubscribe(); }}Forgetting to unsubscribe is a common source of memory leaks in Angular apps. ngOnDestroy is where you prevent them.
Exercise
Section titled “Exercise”- In your practice project, add
implements OnInitto yourGreetingcomponent. - Add a
ngOnInit()method that sets a propertyloadedAtto the current time:this.loadedAt = new Date().toLocaleTimeString(). - Display
loadedAtin the template. - Run the app and confirm the time appears.
- Add
implements OnDestroyand angOnDestroy()that logs'Greeting destroyed'to the console. Navigate to another route (add a simple second route) and confirm the message logs.
- Angular components have a lifecycle with hooks that fire at specific moments.
ngOnInitfires after inputs are set — use it for data fetching and setup logic.- Do not put side effects in the constructor; use it only for dependency injection.
ngOnDestroyfires before the component is removed — use it to cancel subscriptions and clear timers.- Implement the
OnInitandOnDestroyinterfaces to get TypeScript type checking on your hook methods.