# Server Side Rendering (SSR)

When using Server Side Rendering you would want to avoid double data load for same page.\
To atchieve this you have to do two steps:

1. Save state when on server
2. Load state when on browser

this can be attchieved in your `app.module.ts` like:

```typescript
export class AppModule {
    private transferStateKey = makeStateKey(TRANSFER_STATE_KEY);

    constructor(
        private store: Store<MarketplaceState>,
        private platform: PlatformService,
        private transferState: TransferState,
        private dataStrategy: DataStrategy,
    ) {
        if (!this.platform.isBrowser) {
            this.saveState();
        } else {
            this.loadState();
        }
    }

    private saveState() {
        this.store.pipe(takeWhile(() => !this.platform.isBrowser)).subscribe((state) => {
            this.transferState.set(this.transferStateKey, this.dataStrategy.toJS(state));
        });
    }

    private loadState() {
        if (!this.transferState.hasKey(this.transferStateKey)) {
            return;
        }

        const state = this.transferState.get(this.transferStateKey, {} as any);
        this.store.update((s) => {
            this.dataStrategy.merge(s, state, [], true);
            s.dataRestoredFromSSR = true;
        });

        this.removeRestoredFromSSRFlag();
    }

    private removeRestoredFromSSRFlag() {
        document.addEventListener('readystatechange', (event: any) => {
            if (event.target.readyState === 'complete') {
                this.store.update((s) => {
                    s.dataRestoredFromSSR = false;
                });

                document.removeEventListener('readystatechange', (_) => {});
            }
        });
    }
}
```

Lets break this code

1. `saveState` method saves all state changes until on server
2. `loadState` method checks if saved state exists and if so loads it and merges onto the store and sets `dataRestoredFromSSR` to true. After we listen to page finish loading event in order to set `dataRestoredFromSSR` back to false.

{% hint style="info" %}
dataRestoredFromSSR allows us to prevent all http calls until page is loaded - meaning that we will not hit server with repetetive requests for data that has been already loaded and restored.
{% endhint %}

Our http requests might look like this

```typescript
this.http.post(url, body).pipe(
    withLatestFrom(this.store.map((s) => s.dataRestoredFromSSR)),
    filter(([_, dataRestoredFromSSR]) => !dataRestoredFromSSR),
    map(([response, _]) => response),
    //do the rest like .subscribe
)
```
