DEV Community

Cover image for What Should You Put in a Constructor vs ngOnInit in Angular
Joe Eames for Thinkster

Posted on

What Should You Put in a Constructor vs ngOnInit in Angular

One of the most confusing things when building an Angular component is deciding what to put in the constructor and what to put in the ngOnInit method. Both of these methods are used for similar purposes, both fire once at the beginning of the life of a component, so knowing what to put where can be troublesome. In this article, we'll break down when to use each method, and why, and what to put in them, and what NOT to put in them.

First, let's break down what each method does, and when it's fired.

The constructor is important in a component for two reasons. First, it's a lifecycle method, meaning it is called when the component is constructed, so, therefore, it has an important purpose in that if you want specific code to run at a certain time (during construction) then this is the right place to do it. Second, it's the place where you inject services into the component. It looks like this:

image

Note the use of TypeScript here. First we use the private keyword so that we retain a reference to our actor service. Second, we type the "actorService" variable with the "ActorService" type to let Angular know which service we want.

The ngOnInit method on the other hand, serves only as a lifecycle method, firing when a component is initialized.

Both construction and initialization take place at very similar times in the life of a component. And we often want certain kinds of code to run when our component is "created".

Some typical code to run here would be initializing internal state properties, loading data of which the component is in charge, usually via HTTP calls, calling initial methods on injected services, and starting up processes or calculations.

So should we do this during construction or initialization?

Construction happens when the JavaScript class is constructed. It's essentially the first thing that can happen to a class instance. Initialization, on the other hand, happens after that when the component is fully initialized. In essence, this means when Angular is done plugging all the pieces together.

Using this knowledge we can now look at best practices with these two methods, what to put in each, and what not to put in each.

Construction is first, but happens when the component isn't really a component yet. So therefore the constructor should only contain very basic simple code relating to basic initialization of the class. You will have the injected services, but that's about it. So typically we only put simple quick code such as state initialization. Although it's usually simpler to initialize those properties where they are declared if possible.

So do this:

image

Instead of this:

image

The only time to use the latter method is if you need access to an injected service when initializing state.

The ngOnInit method, on the other hand fires when the component is ready to be a component and ready to get to work. Therefore, just about all startup code should be placed here by default. Whether this is making HTTP calls, making calls to dependent services, or other similar items. We can even put our initial state initialization here and it's just fine. There's no drawback to putting it here instead of in the constructor.

So a quick rule of thumb honestly is to consider code in the constructor to be a code smell, and look at it closely to make sure that it shouldn't actually be in your ngOnInit method.

ngOnInit gotcha:

The ngOnInit method does have one gotcha. And that is that even if we change routes, if we're using the same component for both the previous and current route, then the ngOnInit method isn't fired again.

This commonly happens when looking at the details of an item in a list using a component as the detail view, for example, the details of an actor, and if that view has "next actor" and "previous actor" links. Then clicking those links to view the details of a different actor might change the route, but it doesn't cause the ngOnInit method to fire again. So be careful in this case.

For more on constructors and the ngOnInit method, check out my Fundamentals of Angular course, completely free, on Thinkster.io.

Happy coding!

Signup for my newsletter here.

Visit Us: thinkster.io | Facebook: @gothinkster | Twitter: @gothinkster

Top comments (2)

Collapse
 
dsebastien profile image
Sébastien D.

Good points. Although, I personally prefer to put what I can (and what makes sense wrt inputs of the components) in the constructor, as it allows for better type safety (avoid overuse of the definite assignment operator): medium.com/javascript-in-plain-eng...

Collapse
 
gerzah profile image
GerZah

Hi,

you said:

The only time to use the latter method is if you need access to an injected service when initializing state.

Yes, that happens all the time. Now please imagine the following scenario:

class MyComponent {
  editing: boolean;

  constructor(private someInject: SomeInject) {
    this.editing = this.someInject.isEditing();
  }
}
Enter fullscreen mode Exit fullscreen mode

vs.

class MyComponent {
  editing: boolean = this.someInject.isEditing();

  constructor(private someInject: SomeInject) { }
}
Enter fullscreen mode Exit fullscreen mode

It is my understanding that these two approaches are pretty much equivalent. One might ponder over the execution order, as it seems that the property init editing:boolean = this.someInject.isEditing(); in the second example comes before the constructor has even injected the private someInject: SomeInject dependency.

Then again: The property init simply can't be executed before the constructor injects this.someInject, so Typescript seems to take care of that. The question is just: Is the constructor method body run before the property inits or after?

I'd love to hear your thoughts about this.