tldr;
Each Angular component has a lifecycle that lasts from the time the component is added to the page until it is removed from the page. There are several times to hook into the lifecycle, where you can run some code necessary for the component. We’ll look at a few of the most common hooks.
Angular Lifecycle Hooks
Angular has several lifecycle hooks, which you can view in detail on the docs. Here’s the list of hooks:
ngOnChanges
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
ngOnDestroy
Each of the above lifecycle hooks run at various times during the lifecycle of the component. Depending on your needs you can run code when those events occur. Some are more useful and more commonly used than others. Let’s look at some examples of the hooks which I believe are most useful.
ngOnInit
Let’s start with what is likely the most common lifecycle hook, ngOnInit
. This hook is used to initialize certain information or data used in the component. It’s run once, after ngOnChanges
is run. If you’ve worked in an Angular component at all, you’ve likely seen and used ngOnInit
.
There is one main “gotcha” to remember with this lifecycle hook. If the component’s data is changed, but it remains on the screen, ngOnInit
does not run again. This includes when a component is used for a route in your app. Let’s say we have a DetailComponent
that shows the detail of a user. The userId
is pulled from the route params and the data is shown on the page. If you route to the detail of a new user, the data will need to change but ngOnInit
will not be run again, even though the route changes.
Here’s a brief example of an ngOnInit
method:
ngOnInit() {
this.results = this._dataService.getResults();
}
ngOnChanges
The next hook we’ll look at is ngOnChanges
. This hook is used to respond to changes to the data that’s passed in to a component. It is run any time the data-bound properties of the component change. The first time it's run is before ngOnInit
is run.
A good use case for ngOnChanges
is when a component has some data passed in, and subsequent calculations need to be made with that data to display in the component. If you were to make the calculations in the ngOnInit
hook, the data would not update as you expect or desire when the inputs are changed. This is due to ngOnInit
only being run once.
Here’s an example of what may happen in the ngOnChanges
method:
ngOnChanges(changes: SimpleChanges) {
this.total = this.inputOne + this.inputTwo;
}
The ngOnChanges
hook takes an optional argument of type SimpleChanges
. Each attribute on the SimpleChanges
object has three attributes: currentValue
, previousValue
, and firstChange
. Those three attributes are included on an interface called SimpleChange
. These attributes are pretty self explanatory, and allow you to react however you need to in your components. The only attributes present on the SimpleChanges
object are ones that changed in that particular run. So, if inputOne
changes, but not inputTwo
, then the object would look like this:
{
"inputOne": {
"previousValue": 1,
"currentValue": 2,
"firstChange": false
}
}
If the data in your component should be re-calculated when the inputs change, use the ngOnChanges
hook.
ngAfterViewInit
The AfterViewInit
hook allows you to respond when the component’s view and child views are visible on the screen. This hook runs just once, after the first time ngAfterContentChecked
is run.
The ngAfterViewInit
hook is perfect when you need to reference an element of the component’s template inside the TypeScript class. If you try and reference the element in the ngOnInit
hook, there is a good chance that the variable will still be undefined
. Waiting until the ngAfterViewInit
hook runs ensures that the element will be in the screen, provided it’s not been removed from the screen with the *ngIf
directive.
Here’s an example of using the ngAfterViewInit
hook:
export class DemoComponent implements AfterViewInit {
@ViewChild('myElement') myElement: ElementRef;
ngOnInit() {
console.log(this.myElement); // undefined
}
ngAfterViewInit() {
console.log(this.myElement); // ElementRef { ... }
}
}
ngOnDestroy
The ngOnDestroy
hook is run when Angular removes the component from the application. It can be used for cleanup of the component, including unsubscribing from long-lived observables or removing event handlers.
It’s important to remember that Angular needs to remove the component from the app for the hook to run. If you refresh or close the browser tab, the component is technically removed from the browser, but Angular didn’t control the removal of the component. Thus, the ngOnDestroy
hook is not run.
Here’s an example of using the ngOnDestroy
hook:
private subscription;
ngOnInit() {
this.subscription = this.someService.appState.pipe().subscribe();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
- Best practice is to subscribe to observables using the
async
pipe. If you do that, there’s no need to clean up subscriptions in thengOnDestroy
hook. However, some situations require you to subscribe to the observable in the TypeScript file and this will allow you to unsubscribe from the Observable and prevent memory leaks in your app.
Conclusion
In my experience, these are the most used lifecycle hooks. Understanding how they are used and in what situations will allow you to be most effective when writing your Angular apps. The other hooks I mentioned at the beginning of the article can also be helpful, but aren’t as common as the four covered here
Top comments (0)