# Common props

Common props are props that are available for each `Next` page that is server-side rendered via `getServerSideProps`.

## Motivation

We need to have access to some specific information on every page. `Next` offers its own way of handling common/global props via declaring an `_app.js` page. This method, however, comes with limitations and doesn't support `Next` data fetching methods like `getServerSideProps` and `getStaticProps`.

With the extensibility that is achieved in Mosaic, it's possible to declare a new namespace `Pages/getCommonServerSideProps` that will be the default output of each `getServerSideProps` function in the app.

## Extensibility

`Pages/getCommonServerSideProps` is a fixed namespace, meaning that any module can plug into it, make changes, and these changes will be reflected in all `Next` pages in the app. By default, each `Next` page are assigned these values:

```javascript
/** @namespace Pages/getCommonServerSideProps */
const getCommonServerSideProps = () => ({ props: {} });

/** @namespace <%= server_namespace %> */
const getServerSideProps = () => getCommonServerSideProps();
```

In order to add new common props, a plugin has to be created extending the `Page/getCommonServerSideProps` namespace. An example of adding a synchronous variable to the common props:

```javascript
const addStoreNameToCommonProps = async (args, callback) => {
    const commonProps = await callback(...args);

    return {
        props: {
            ...commonProps.props,
            storeName: 'My awesome store'
        }
    };
};

export default {
    'Pages/getCommonServerSideProps': {
        function: addStoreNameToCommonProps
    }
};
```

Note one important thing in the code above, **the callback output is awaited for**. This is important to keep in mind, as common props could also contain asynchronous variables:

```javascript
const addPaymentProvidersToCommonProps = async (args, callback) => {
    const commonProps = await callback(...args);
    const paymentProviders = await requestPaymentProviders();

    return {
        props: {
            ...commonProps.props,
            paymentProviders
        }
    };
};

export default {
    'Pages/getCommonServerSideProps': {
        function: addPaymentProvidersToCommonProps
    }
};
```

{% hint style="warning" %}
Always make sure to always use `await` before `callback(...args)`!
{% endhint %}

## Usage

As mentioned above, the `getServerSideProps` function for each `Next` page will return the common props by default. This is an example of combining the common props with page-specific props:

```javascript
const getServerSideProps = async (args, callback) => {
    const commonProps = await callback(...args);
    const pageProps = await requestPageProps();

    return {
        props: {
            ...commonProps.props,
            ...pageProps
        }
    };
};

export default {
    'Pages/my-page/getServerSideProps': {
        function: getServerSideProps
    }
};
```

Very few pages, if any, are going to use all of the common props. Due to that, it's recommended to extract the specific common props that the page uses and ignore the rest. Let's adjust the code to only retrieve `storeName` from the common props:

```javascript
const getServerSideProps = async (args, callback) => {
    const { props: { storeName } } = await callback(...args);
    const pageProps = await requestPageProps();

    return {
        props: {
            ...pageProps,
            storeName
        }
    };
};

export default {
    'Pages/my-page/getServerSideProps': {
        function: getServerSideProps
    }
};
```

This way if new entries are added to the common props, they won't be sent to props of that page automatically. This also prevents potential overrides if the name of a common props matches the name of a page prop.

## Working with common props

Before starting to add variables to common props, it's crucial to understand the purpose of such solution.

{% hint style="warning" %}
Common props are **render-blocking**. This means that unless **ALL** API requests within the common props are either resolved or rejected, the page will not load. Be careful with 3rd-party APIs and always specify a timeout to all requests, just in case!
{% endhint %}

Common props **are**:

* A convenient way of delcaring **static** data accross pages,
* Great for making API requests that are made on each page such as configuration fetching.

Common props are **not**:

* A Redux store. Data flows in one way - from the `getCommonServerSideProps` to a page - there are no actions to modify the common props from a page,
* Designed to store any dynamic data. These props are fetched once during the server-side rendering and won't react to any further changes.
