The DestroyRef has been introduced in Angular 16 (commit link),and gives us the option to run a callback function when the component/directive is destroyed, or when the corresponding injector is destroyed.
Let's see an easy example to understand how we can use that.
Callback when a component is being destroyed
The code above emits a new value every 1 sec (1000ms) and logs a value to the console. It's a small piece of code but still it creates a memory leak since we are not destroying the subscription.
Let's answer some questions.
Despite that the component is destroyed, the subscription remains active.
We have to unsubscribe the subscription to avoid creating a memory leak. But perhaps you are already doing this 👍
Let's do the same but this time using the DestroyRef
Let's read the code from top to bottom.
Alternatively we could write the same piece of code like that:
Note, this time we are using the inject function in the constructor. This still works fine since we are in the injection context.
There is a better way to unsubscribe though, keep reading :)
There is a better way to unsubscribe but let's first see some important details.
I have created the method myTakeUntilDestroyed which injects the DestroyRef.
It's important to understand that we cannot use the inject method outside the injection context.
In the example above, I call the myTakeUntilDestroyed from the constructor which works fine.
Injection Context: Constructor, class fields, factory method. Read more
What would happen if we call the method from the ngOnInit hook?
Since we are not in the injection context, Angular will throw an error.
If we, however, have to call the myTakeUntilDestroyed from the ngOnInit hook, we should change how we access the DestroyRef.
This change ensures that the developer will provide the DestroyRef when outside of the injection context. As such, the code will become:
So far we have covered some important details, and we are ready now to start using the takeUntilDestroyed rxjs operator.
The takeUntilDestroyed completes the observable when the component/directive is destroyed, or when the corresponding injector is destroyed!
That's great! We have achieved the same with less and easy to read code. Nice!
Oh wait, how about the ngOnInit hook?