Gaurav Aggarwal
Gaurav Aggarwal

Reputation: 10187

Angular 7 SSR, App component ngOnInit() called multiple times

I have an angular 7 application with about 30 modules. I am fetching user details in app.component.ts to use it throughout the application but I suddenly noticed that user details API runs multiple times on 1 load.

After putting logs in ngOnInit() in my app.component.ts I found that logs are printing multiple times but it's happening only on server-side rending on the browser it renders only once.

Any idea why ngOnInit() calls more than once??

Upvotes: 4

Views: 3214

Answers (4)

VISHNU
VISHNU

Reputation: 966

In SSR other than afterRender and afterNextRender the constructor and initial life cycle hooks will execute both on the server and in the browser.

We can implement caching for httpClient calls to avoid multiple api calls. bootstrapApplication(AppComponent, { providers: [ provideClientHydration(withHttpTransferCacheOptions({ includePostRequests: true })) ] });

Or we can use PLATFORM_ID with isPlatformBrowser and isPlatformServer to identify if it is rendering in server or client

import { PLATFORM_ID } from '@angular/core';
import {  isPlatformBrowser, isPlatformServer } from '@angular/common';
ngOnInit(): void {
    if(isPlatformBrowser(this.platformId)){
      // runs on client / browser
      console.log("from browser.");
    }
    if(isPlatformServer(this.platformId)){
      // runs on server / node
      console.log("from server");
    }
  }

Upvotes: 0

Furqan Rahamath
Furqan Rahamath

Reputation: 2076

I am not sure if this solved yet, but here is one suggestion:

Add the subscribe part in your component itself and remove it from your function which makes HTTP call:

ngOnInit() {
    this.loadData();
}

loadData(){
    this.my_service.getData().subscribe(data => this.userDetails = data);
}

And in your service, you can have a plain HTTP call:

getData() {
    return this.http.get('../your/url')
           .map((res:Response) => res.json());
}

I hope this helps.

Upvotes: 0

Sunny
Sunny

Reputation: 143

The ngOnInit() hooks only once after all directives are instantiated. If you have subscription inside ngOnInit() and it's not unsubscribed then it will run again if the subscribed data changes. In your case when loading API calls via SSR on the server side, the server does not always wait for the response to come and probably that can be a reason for multiple logs. A suggestion will be to delegate this on the client side using isPlatformBrowser. This is what it looks to me based on the investigation of general SSR flow.

Upvotes: 0

vivek
vivek

Reputation: 181

Concept of Angular SSR is that on 1st load of page/URL it renders through server and then transfer data on client side. So Technically it calls all the components, services exist on that page/URL twice.

You can use condition isPlatformBrowser and isPlatformServer method, so you can render only required part on server side. We render only specific thing on SSR which are related to SEO optimisation.

Upvotes: 3

Related Questions