
As an Angular developer, you’ve likely used lifecycle hooks such as ngOnChanges, ngOnInit, and ngOnDestroy. With the advent of Zoneless and Signals, we can use better, more readable options.
Alain Chautard
May 19, 2026
Let’s check them out:
ngOnChanges with computed()Previously, ngOnChanges was required to react to @Input changes and update derived state. With Signal inputs, computed handles this automatically, lazily, and without side effects.
Here is an example with before/after code.
@Component({...})
export class PricingComponent implements OnChanges {
@Input() price = 0;
totalPrice = 0;
constructor(private taxService: TaxService) {}
ngOnChanges(changes: SimpleChanges) {
if (changes['price']) {
// Calling the service when the input updates
this.totalPrice = this.taxService.calculateTotal(this.price);
}
}
}
After — computed:
@Component({...})
export class PricingComponent {
price = input<number>(0);
private taxService = inject(TaxService);
// Calling the service when the input updates
totalPrice = computed(() => this.taxService.calculateTotal(this.price()));
}
Using Signals is not only more performant, but it's also more concise and readable.
ngOnInit was often used as a safe place to initialize data once inputs were available. With Signals and modern reactivity, initialization can often happen declaratively at the property level.
Before — ngOnInit:
@Component({...})
export class UserComponent implements OnInit {
@Input() userId!: string;
userData!: User;
constructor(private userService: UserService) {}
ngOnInit() {
// Relying on ngOnInit to ensure userId is ready
this.userData = this.userService.getUserSync(this.userId);
}
}
After — signal-based:
@Component({...})
export class UserComponent {
userId = input.required<string>();
private userService = inject(UserService);
// Derives the user data reactively without needing a hook
userData = computed(() => this.userService.getUserSync(this.userId()));
}
The signal-based option is even better as it would react to subsequent updates ot the userId input, if that ever happens.
Manually storing Subscription arrays or other techniques inside ngOnDestroy is no longer necessary thanks to takeUntilDestroyed().
Before — manual subscription and unsubscription:
@Component({...})
export class AlertComponent implements OnDestroy {
private sub: Subscription;
constructor(private alertService: AlertService) {
this.sub = this.alertService.alerts$
.subscribe(alert => console.log(alert));
}
ngOnDestroy() {
this.sub.unsubscribe();
}
}
After — takeUntilDestroyed:
@Component({...})
export class AlertComponent {
constructor(private alertService: AlertService) {
this.alertService.alerts$
.pipe(takeUntilDestroyed())
.subscribe(alert => console.log(alert));
}
}
Here again, the approach is more concise and readable. And, of course, replacing RxJs entirely with Signals would simplify this even further (I have some good tips about that Signal migration here).
As we can see, lifecycle hooks can be replaced with a more maintainable option most of the time. Lifecycle hooks aren’t dead, but they are now specialized tools rather than everyday necessities (e.g., you still need ngAfterViewInit for direct DOM/canvas manipulation).
Get the latest news and updates on developer certifications. Content is updated regularly, so please make sure to bookmark this page or sign up to get the latest content directly in your inbox.

Error Handling in Next.js with catchError
Learn why react-error-boundary falls short in the Next.js App Router and how catchError from Next.js 16.2 fixes both framework error propagation and server data refetching with a single function call.
Aurora Scharff
Jun 18, 2026

SEO in Nuxt with @nuxtjs/seo
Set up sitemaps, meta tags, structured data, OG images, and robots.txt in Nuxt with the official SEO module.
Reza Baar
Jun 17, 2026
![What’s the untracked function? [Angular Signals]](/.netlify/images?url=https:%2F%2Fapi.certificates.dev%2Fstorage%2FZzk75tZNAVT5d3GI9TxAD2JwkIFUKavFFj8sC2BL.png)
What’s the untracked function? [Angular Signals]
Learn how Angular's computed() function derives reactive values from signals and why it plays a key role in building high-performance, signal-based applications with cleaner and more predictable state management.
Alain Chautard
Jun 16, 2026