Next.js: async getInitialProps on Layout not working

Created on 30 Jan 2017  路  11Comments  路  Source: vercel/next.js

Hi,
Can layout and children component both be async, I am trying out but it seems that only children component getInitialProps is getting called. Please verfiy.

./components/layout.js

export default class Layout extends React.Component {
    static async getInitialProps (props) {
        const headerResponse = await fetch(someapi)
        console.log(headerResponse)
        return {...props, headerData: "headerResponse"}
    }

    render() {
        const {headerData, children} = this.props
        return (
            <div>
                <Head>
                    <title>Next js test</title>
                    <meta charSet='utf-8' />
                    <meta name='viewport' content='initial-scale=1.0, width=device-width' />
                </Head>
                <header>
                    This is header section
                </header>

                {children}

                <footer>
                    This is the footer section
                </footer>
            </div>
        )
    }
}

./pages/index.js

export default class Home extends React.Component {
    static async getInitialProps () {
        const homeResponse = await fetch(someapi2)
        return {homeData: homeResponse}
    }

    render() {
        const {homeData} = this.props
        return (
            <Layout>
                <div>Welcome from Next.js</div>
            </Layout>
        )
    }
}

Most helpful comment

@arunoda - I wanted to make a layout that allows getInitialProps to fetch data from remote api and content of the app should be page component which also have getInitialProps and requires separate api call. On Client only page content is supposed to change and Layout doesn't reload at all.

Api on the Layout would generate links for other pages. So Link component is required in layout
Can you please suggest a way?

All 11 comments

layout.js is not supported. You can use _document.js as described here: https://github.com/zeit/next.js#custom-document

Hi @timneutkens, Thanks for your quick response and resolving query. Next.js is looking good for starters as well.
Now that I am able to use async in Document and Nested component.
However I have two links using (Link component) and I don't want to reload Layout component's data once loaded. However I can see in network tab all javascript is being loaded again

image

Actually, just noticed there is a new example. I Will have to try that one to make sure it works as expected.

@arunoda could you have a look at:

Hi @timneutkens, Thanks for your quick response and resolving query. Next.js is looking good for starters as well.
Now that I am able to use async in Document and Nested component.
However I have two links using (Link component) and I don't want to reload Layout component's data once loaded. However I can see in network tab all javascript is being loaded again

@timneutkens It's really hard to say anything without looking at a sample repo.
@rohitpal99 could you provide a sample repo?

@arunoda - Here is the repo

@rohitpal99 do not put Link inside the _document.
It's only for setting up the initial HTML layout.

Check this: https://github.com/zeit/next.js/issues/885#issuecomment-275291842

Do all the liking and layout stuff in you pages

@arunoda - I wanted to make a layout that allows getInitialProps to fetch data from remote api and content of the app should be page component which also have getInitialProps and requires separate api call. On Client only page content is supposed to change and Layout doesn't reload at all.

Api on the Layout would generate links for other pages. So Link component is required in layout
Can you please suggest a way?

Agree with @rohitpal99 , to build an "Application Shell" that requires async data (for navigation, footer, etc.), we need to fetch data for Layout in getInitialProps. And this "Application Shell" should not reload between pages, similar to PWA.

Is there any other way we can get it done besides put everything from Layout into ./pages/_document.js?

@rohitpal99 any info to how to do that? Fetching async data in getInitialProps?

To create a layout component to fetch generic app data like the user you can create a high order component and wrap your pages with it, the HOC should have this logic:

  • check if it's running client or server side
  • if it's client side check in an in-memory cache (or sessionStorage) if already has the data
  • if it doesn't have the data or is server side fetch it
  • call the getInitialProps (if it exists) of the wrapped page

Then you can also define some custom UI and render the page component inside it (like a navigation, etc.)

Was this page helpful?
0 / 5 - 0 ratings