To destroy the subscription used in the component manually is a tedious task, so in order to solve this issue a solution is provided which automatically unsubscribes the subscription as soon as the component is destroyed.
In Angular 16, we were introduced to a new method called takeUntilDestroyed(). This method completes the Observable when the calling context (component, directive, service, etc) is destroyed.
import { Component } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
@Component({
selector: "my-component",
templateUrl: "./my-component.html",
styleUrls: ["./my-component.scss"]
})
export class MyComponent {
constructor(private http: HttpClient) {
this.http.get('/api').pipe(takeUntilDestroyed()).subscribe();
}
}
NOTE: If you are trying to do the same outside of the constructor you may see this error takeUntilDestroyed() can only be used within an injection context such as a constructor To fix this update to the following
import { Component, DestroyRef, OnInit, inject } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
@Component({
selector: "my-component",
templateUrl: "./my-component.html",
styleUrls: ["./my-component.scss"]
})
export class MyComponent implements OnInit {
destroyedRef = inject(DestroyRef);
ngOnInit(): void {
this.http.get('/api').pipe(takeUntilDestroyed(this.destroyedRef)).subscribe();
}
}
In this version, we only had the takeUntil() method, so we had to rely on a subject variable in order to store the reference for the subscription.
Note the use of the pipe() method.
class myComponent {
private destroyed$: ReplaySubject = new ReplaySubject(1);
constructor( private serviceA: ServiceA, private serviceB: ServiceB, private serviceC: ServiceC) {}
ngOnInit() {
this.serviceA .pipe(takeUntil(this.destroyed$)) .subscribe(...);
this.serviceB .pipe(takeUntil(this.destroyed$)) .subscribe(...);
this.serviceC .pipe(takeUntil(this.destroyed$)) .subscribe(...);
}
ngOnDestroy() {
this.destroyed$.next(true); this.destroyed$.complete();
}
}
class myComponentOld {
private destroyed$: ReplaySubject = new ReplaySubject(1);
constructor(private serviceA: ServiceA) {}
ngOnInit() {
this.serviceA .takeUntil(this.destroyed$) .subscribe(...);
}
ngOnDestroy() {
this.destroyed$.next(true); this.destroyed$.complete();
}
}
Work with our skilled Angular developers to accelerate your project and boost its performance.
Hire Angular Developers