takeUntilDestroyed Angular New Way to Unsubscribe

In this post we will look on takeUntilDestroyed method that we got inside Angular 16.

I'm sure you remember that inside Angular we must always unsubscribe from our subscriptions to avoid memory leaks.

export class PostsComponent implements OnInit {
  data$ = interval(1000);
  unsubscribe$ = new Subject<void>();

  ngOnInit(): void {
    this.data$.pipe(takeUntil(this.unsubscribe$)).subscribe((data) => {
      console.log('data', data);
    });
  }

  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}

Here I have a PostsComponent with an interval of data inside. Inside ngOnInit we are subscribing to this stream and logging our data.

Working stream

When we go to the Posts page we can see logs from our stream. But when we just to Home page our stream stops because we unsubscribed from the stream. This is exactly why here we need unsubscribe Subject and takeUntil.

In Angular we have different ways to unsubscribe from the subscriptions but takeUntil is the most flexible and requires the least amount of code.

But starting from Angular 16 it is even better. As this takeUntil approach was the most popular we got a helper takeUntilDestroyed from Angular.

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

...

export class PostsComponent implements OnInit {
  ...
  ngOnInit(): void {
    this.data$.pipe(takeUntilDestroyed()).subscribe((data) => {
      console.log('data', data);
    });
  }
}

So instead of all code with Subject that we have previously we can just import takeUntilDestroyed and use it inside the pipe.

Error

We didn't get any errors inside Typescript but in browser you can see this error. It means that we can use takeUntilDestroyed only in construction phase and not just anywhere in our code.

Construction phase inside component is either in constructor or by defining values in class.

Which means we need to move our takeUntilDestroyed to another place.

export class PostsComponent implements OnInit {
  data$ = interval(1000).pipe(takeUntilDestroyed())

  ngOnInit(): void {
    this.data$.subscribe((data) => {
      console.log('data', data);
    });
  }
}

Here we attached takeUntilDestroyed to our interval. It won't throw any errors because it is a construction phase. Our code is super clean now as there are no pipes in ngOnInit at all.

This is the 99% of the cases how you want to write your code.

Not construction phase

But maybe you have a case when you really need to use takeUntilDestroyed in other place (like ngOnInit). We can use that but will a bit of code.

export class PostsComponent implements OnInit {
  data$ = interval(1000);
  destroyRef = inject(DestroyRef);

  ngOnInit(): void {
    this.data$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((data) => {
      console.log('data', data);
    });
  }
}

Here we injected DestroyRef and provided it to takeUntilDestroyed method inside ngOnInit. It won't throw any errors because we provided the destroy reference of our component inside from construction phase.

If you want to use takeUntilDestroyed anywhere you need to provide destroyRef inside.

Working stream

As you can see in browser our stream is being canceled like before but we wrote much less code here.

Want to conquer your next JavaScript interview? Download my FREE PDF - Pass Your JS Interview with Confidence and start preparing for success today!

📚 Source code of what we've done
Did you like my post? Share it with friends!
Don't miss a thing!
Follow me on Youtube, Twitter or Instagram.
Oleksandr Kocherhin
Oleksandr Kocherhin is a full-stack developer with a passion for learning and sharing knowledge on Monsterlessons Academy and on his YouTube channel. With around 15 years of programming experience and nearly 9 years of teaching, he has a deep understanding of both disciplines. He believes in learning by doing, a philosophy that is reflected in every course he teaches. He loves exploring new web and mobile technologies, and his courses are designed to give students an edge in the fast-moving tech industry.