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:

/** @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:

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:

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
    }
};

Always make sure to always use await before callback(...args)!

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:

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:

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.

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!

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.

Last updated