What is @ngneat/until-destroy?
@ngneat/until-destroy is an Angular utility that helps manage the lifecycle of subscriptions and other resources in Angular components and services. It automatically unsubscribes from observables when the component or service is destroyed, preventing memory leaks and reducing boilerplate code.
What are @ngneat/until-destroy's main functionalities?
Automatic Unsubscription
This feature allows automatic unsubscription from observables when the component is destroyed. The `untilDestroyed` operator is used to bind the observable to the component's lifecycle.
import { Component } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { interval } from 'rxjs';
@UntilDestroy()
@Component({
selector: 'app-example',
template: '<p>Example works!</p>'
})
export class ExampleComponent {
constructor() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe(val => console.log(val));
}
}
Service Support
This feature extends the automatic unsubscription functionality to services. The `untilDestroyed` operator can be used in services to manage subscriptions and other resources.
import { Injectable } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { interval } from 'rxjs';
@UntilDestroy()
@Injectable({
providedIn: 'root'
})
export class ExampleService {
constructor() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe(val => console.log(val));
}
}
Directive Support
This feature allows the use of `untilDestroyed` in directives, providing the same automatic unsubscription functionality as in components and services.
import { Directive, OnDestroy } from '@angular/core';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { interval } from 'rxjs';
@UntilDestroy()
@Directive({
selector: '[appExample]'
})
export class ExampleDirective implements OnDestroy {
constructor() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe(val => console.log(val));
}
ngOnDestroy() {
// Custom cleanup logic if needed
}
}
Other packages similar to @ngneat/until-destroy
ngx-take-until-destroy
ngx-take-until-destroy is another Angular utility for managing subscriptions. It provides a similar functionality to @ngneat/until-destroy by using a `takeUntilDestroy` operator to handle unsubscriptions. However, @ngneat/until-destroy offers a more modern and streamlined API.
take-until-destroy
take-until-destroy is a lightweight library that helps manage subscriptions in Angular components. It uses a `takeUntil` operator to unsubscribe from observables. While it provides similar functionality, @ngneat/until-destroy offers a more comprehensive and integrated solution.
🦁 Unsubscribe For Pros
A neat way to unsubscribe from observables when the component destroyed
Compatibility with Angular Versions
@ngneat/until-destroy | Angular |
---|
8.x
|
>= 10.0.5 < 13
|
9.x
|
>= 13
|
Table of contents
Angular 10 Compatibility
@ngneat/until-destroy@8+
is compatible only with Angular starting from 10.0.5 version. @ngneat/until-destroy@7
is compatible with Angular versions below 10.0.5. If you have noticed that unsubscribing does not work after some update then check the version of Angular and @ngneat/until-destroy
first of all.
Use with Ivy
npm install @ngneat/until-destroy
yarn add @ngneat/until-destroy
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
@UntilDestroy()
@Component({})
export class InboxComponent {
ngOnInit() {
interval(1000).pipe(untilDestroyed(this)).subscribe();
}
}
You can set the checkProperties
option to true
if you want to unsubscribe from subscriptions properties automatically:
@UntilDestroy({ checkProperties: true })
@Component({})
export class HomeComponent {
subscription = fromEvent(document, 'mousemove').subscribe();
}
You can set the arrayName
property if you want to unsubscribe from each subscription in the specified array.
@UntilDestroy({ arrayName: 'subscriptions' })
@Component({})
export class HomeComponent {
subscriptions = [
fromEvent(document, 'click').subscribe(),
fromEvent(document, 'mousemove').subscribe(),
];
ngOnInit() {
interval(1000).pipe(untilDestroyed(this));
}
}
You can set the blackList
property if you don't want to unsubscribe from one or more subscriptions.
@UntilDestroy({ checkProperties: true, blackList: ['subscription1'] })
@Component({})
export class HomeComponent {
subscription1: Subscription;
subscription2: Subscription;
constructor() {
this.subscription1 = new Subject().subscribe();
this.subscription2 = new Subject().subscribe();
}
}
Use with Non-Singleton Services
@UntilDestroy()
@Injectable()
export class InboxService {
constructor() {
interval(1000).pipe(untilDestroyed(this)).subscribe();
}
}
@Component({
providers: [InboxService],
})
export class InboxComponent {
constructor(inboxService: InboxService) {}
}
All options, described above, are also applicable to providers.
Use with View Engine (Pre Ivy)
npm install ngx-take-until-destroy
yarn add ngx-take-until-destroy
import { untilDestroyed } from 'ngx-take-until-destroy';
@Component({})
export class InboxComponent implements OnDestroy {
ngOnInit() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe(val => console.log(val));
}
ngOnDestroy() {
}
}
Use with Any Class
import { untilDestroyed } from 'ngx-take-until-destroy';
export class Widget {
constructor() {
interval(1000).pipe(untilDestroyed(this, 'destroy')).subscribe(console.log);
}
destroy() {}
}
Migration from View Engine to Ivy
To make it easier for you to migrate, we've built a script that will update the imports path and add the decorator for you. The script is shipped as a separate package. Run the following command to install it:
npm i --save-dev @ngneat/until-destroy-migration
yarn add -D @ngneat/until-destroy-migration
Then run the following command:
npx @ngneat/until-destroy-migration --base my/path
base
defaults to ./src/app
.
You can use the --removeOnDestroy
flag for empty OnDestroy
methods removing.
npx @ngneat/until-destroy-migration --removeOnDestroy
You can remove the package once the migration is done.
Potential Pitfalls
- The order of decorators is important, make sure to put
@UntilDestroy()
before the @Component()
decorator. - When using
overrideComponent
in unit tests remember that it overrides metadata and component definition. Invoke UntilDestroy()(YourComponent);
to reapply the decorator. See here for an example.
ESLint Rules
Contributors ✨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!