Getting to Know the DestroyRef Provider in Angular
Angular v16 has introduced a new provider called DestroyRef
, which allows for registering destroy callbacks for a specific lifecycle scope. This feature is applicable to components, directives, pipes, embedded views, and instances of EnvironmentInjector
.
The usage of DestroyRef
is straightforward. We can inject the DestroyRef
provider and register a destroy
callback like so:
@Component({
selector: 'foo',
standalone: true,
template: '',
})
class FooComponent {
constructor() {
inject(DestroyRef).onDestroy(() => {
// do something when the component is destroyed
})
}
}
You might wonder, “Isn’t the ngOnDestroy hook already available in Angular? Why do we need DestroyRef?”
Using DestroyRef
, it’s possible to create reusable logic that performs necessary cleanup tasks when a scope
is destroyed without the need for inheritance. This simplifies the implementation process and reduces complexity.
For example, we can create an untilDestroyed
operator that relies on DestroyRef
:
export function untilDestroyed() {
const subject = new Subject();
inject(DestroyRef).onDestroy(() => {
subject.next(true);
subject.complete();
});
return <T>() => takeUntil<T>(subject.asObservable());
}
@Directive({
selector: '[appFoo]',
standalone: true,
})
export class FooDirective {
private untilDestroyed = untilDestroyed();
ngOnInit() {
interval(1000)
.pipe(this.untilDestroyed())
.subscribe(console.log);
}
}
Follow me on Medium or Twitter to read more about Angular and JS!