DEV Community

Preston Lamb
Preston Lamb

Posted on • Originally published at prestonlamb.com on

Angular Lifecycle Hooks

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();
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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 { ... }
  }
}
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode
  • Best practice is to subscribe to observables using the async pipe. If you do that, there’s no need to clean up subscriptions in the ngOnDestroy 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)