angularngrxangular-ssrngrx-component-store

Why does my page render timeout on refresh when using SSR and ComponentStore in Angular 18?


We're using Angular 18, with SSR enabled.

I have created a component that uses a ComponentStore service. In this component, I am calling a function within the service to load and populate the store with the required data from the API.

@Input({ required: true }) accountId: string = null!;

ngOnInit(): void {
    this.componentStore.getComponentData(this.accountId);
}

The function in the service looks like this:


getComponentData(accountId: string): void {
    of(accountId).pipe(
        filter(accountId => !!accountId),
        take(1),
        switchMap(accountId => {
            return forkJoin([
                this.apiService.getSomeData(accountId),
                this.apiService.getSomeOtherData(accountId)
            ]);
        })
    ).subscribe(([someData, someOtherData]) => {
        this.setData(someData);
        this.setOtherData(someOtherData);
    });
}

readonly setData = this.updater((state, value: IData) => ({
    ...state,
    data: value
}));

When I navigate to the page through the application, the page loads and populates with data correctly. However, when I refresh the page it hangs for 30 seconds and then Angular throws the following error: Page /path/to/page did not render in 30 seconds..

If I remove the call to the componentStore in ngOnInit inside the component, the page will refresh and render, but obviously no data will be retrieved.

I've tried using afterNextRender but the callback doesn't fire and therefore no data is loaded. I'm out of ideas now.

Any extra help would be appreciated.


Solution

  • Whether this is the correct way to go about it I'm not sure, however the issue has been solved by:

    Injecting PLATFORM_ID into the component:

    private readonly platformId = inject(PLATFORM_ID);
    

    Then, wrapping the call to the store service with:

    if (isPlatformBrowser(this.platformId) {
      this.componentStore.getComponentData(this.accountId);
    }
    

    The component now renders and does not timeout.

    This solution feels hacky, but without any other answers it'll have to do for now.