Migrating from until-destroy to takeUntilDestroyed
Migrating from until-destroy to takeUntilDestroyed
We're developing January, a comprehensive platform that enables you to build, integrate, test, and deploy APIs all in one place.Try it for free in the playground and have an API that you can share in seconds.
Angular has been releasing new things nonstop, one of which Is the DestroyRef token, a utility class that provides an onDestroy hook that is called when a component/directive is destroyed.
We already have this with the OnDestroy interface, but the cool thing about DestroyRef is that it works wonderfully with another utility function named takeUntilDestroyed
Before takeUntilDestroyed you’ve to do something similar to unsubscribe from an observable stream$
With DestroyRef and takeUntilDestroyed you can do the following:
Pretty cool, isn’t it?
Previously, I’ve used the fantastic until-destroy package that does what the takeUntilDestroyed does but using a decorator.
Very similar. However, I always prefer to maximize the framework’s usage as much as possible. As we already have a method now to do it the Angular way, I’d instead remove a package from my node_modules
You can change them manually, or you can write a script to modify the code for you. In the last blog, we talked about how we can use TypeScript compiler API to do code modification. This case is one of many that the compiler API excels at. That being said, we are going to use the ts-morph package today:
To learn something.
As of today, you cannot instruct the TypeScript AST printer to respect the original code formatting (although you can apply prettier right after code modification to get it back as it was). Hence, ts-morph
ts-morph offers a friendly API to manipulate the source code
Starting with Installing ts-morph
npm i ts-morph
Create a morph project and select Angular-related files
Keep in mind that you’re only going to migrate the first case of using until-destroy mentioned above. if you’re using checkProperties,arrayName, or blackList, you’ve to improve on the code.
The plan is to iterate over all files from ts-morph and then loop over all classes in each file.
Moving next, you need to filter out the classes that don’t need to be modified. There are four situations where a class is not modifiable:
The class doesn’t have an Angular-related decorator.
The class doesn’t have a UntilDestroy decorator.
The UntilDestroy decorator has options in it.
The untilDestroyed function is not used in the class.
The class doesn’t have an Angular-related decorator.
The class doesn’t have a UntilDestroy decorator.
The UntilDestroy decorator has options in it.
The untilDestroyed function is not used in the class. You need to get all calls to untilDestroyed via querying the class for CallExpression nodes and check the name of each node to equal untilDestroyed
With checks in place, you can move to do the code modification. There are 3 places that can contain an untilDestroyed
Within the constructor
Within a method
Inlined in the class body
So you need to loop over untilDestroyedCalls from above and check where each untilDestroyed call is being used and, based on that fact, invoke the modification logic.
You might have noticied the variable doWeNeedDestroyRef that is used to determine if you need to add the _destroyRef property to the class. If you’re using untilDestroyed within a method, you need to add the _destroyRef property to the class.
Alternativly, you can use _destroyRef with takeUntilDestroyed always and avoid this check.
Last but not least, you need to remove the until-destroy import and UntilDestroy decorator.
Remove the until-destroy import
Finally, you need to ensure the DestroyRef and takeUntilDestroyed imports are set then save the file.
The ts-morph API although simple and to the point it still might confuse you if you're not familiar with the TypeScript compiler API. You can read the Gentle Introduction To Typescript Compiler API to get a better understanding of the TypeScript compiler API.
Make sure to run the script on a clean repository (commit any code) as it will modify the code in place.