Currently there are 3 ways to use getInitialProps:
// pages/_document.js
// `renderPage` refers to the function that renders the page.
import Document from 'next/document'
static async getInitialProps({pathname, query, asPath, req, res, err, renderPage}) {
return await document.getInitialProps({pathname, query, asPath, req, res, err, renderPage})
}
Often used like:
// pages/_document.js
// `renderPage` refers to the function that renders the page.
import Document from 'next/document'
static async getInitialProps(ctx) {
return await document.getInitialProps(ctx)
}
// pages/_app.js
// `Component` refers to the page in the pages dir being rendered
// `ctx` is `{pathname, query, asPath, req, res, err}`
static async getInitialProps({Component, ctx }) {
let pageProps = {}
if(Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
// pages/index.js
// If you define a custom _app.js Next.js actually is no longer in charge of handling it.
// The `Component.getInitialProps` being used in _app.js is actually calling this function
// So that's the `ctx` part you're passing into `Component.getInitialProps`
static async getInitialProps({pathname, query, asPath, req, res, err}) {}
So as you can see the _document and pages getInitialProps are actually mostly similar. With the exception of renderPage.
_app.js on the other hand has the context on a subproperty. This was done at the time to allow for easier passing to the page getInitialProps (Component.getInitialProps)
However as multiple people pointed out it gets confusing when using all of them in your Next.js application as you expect certain values to be there when destructuring but they end up being undefined in _app.js etc. So what I'm proposing is:
// same
// pages/_document.js
// `renderPage` refers to the function that renders the page.
import Document from 'next/document'
static async getInitialProps({pathname, query, asPath, req, res, err, renderPage}) {
return await document.getInitialProps({pathname, query, asPath, req, res, err, renderPage})
}
Often used like:
// same
// pages/_document.js
// `renderPage` refers to the function that renders the page.
import Document from 'next/document'
static async getInitialProps(ctx) {
return await document.getInitialProps(ctx)
}
// pages/_app.js
// Rename `Component` to `Page` to be clearer about what it is
// No longer have `ctx` property but instead have them define in the same way across _document, _app and pages.
static async getInitialProps({Page, pathname, query, asPath, req, res, err}) {
let pageProps = {}
if(Page.getInitialProps) {
pageProps = await Page.getInitialProps({pathname, query, asPath, req, res, err})
}
return { pageProps }
}
// same
// pages/index.js
// If you define a custom _app.js Next.js actually is no longer in charge of handling it.
// The `Page.getInitialProps` being used in _app.js is actually calling this function
// So that's the object you're passing into `Page.getInitialProps`
static async getInitialProps({pathname, query, asPath, req, res, err}) {}
Thanks to the person from http://bango.com who raised this issue the first on spectrum.chat, I can't quite remember the username and can't find the spectrum thread 馃檹
I found this issue from #5311 and I have a question about the use of router in app component's getInitialProps. I want to get the page info of the previous page (like pathname and asPath) in the page component's getInitialProps and act differently based on the values. I found these info in the router param in app component's getInitialProps. I am thinking of passing that to the page component's getInitialProps. But I am hesitant to do that since the router param is removed from the doc now. Thoughts?
Yeah don't use it 馃檹 What do you need the previous page for?
Love the idea of renaming Component to Page! I think it is much clearer.
I'd also like to tack on that this should be clearly documented.
I just stumbled across this and found no mention of the divergent signature for <App> on https://nextjs.org/docs
It actually gives this example, which suggests the same signature as elsewhere:
static async getInitialProps(appContext) {
// calls page's `getInitialProps` and fills `appProps.pageProps`
const appProps = await App.getInitialProps(appContext);
return { ...appProps }
}
I think it is a really good idea to have this standardization.
Moreover, I really like the idea to rename "Component" into "Page" in the _app.js. I found it is very confusing when I began with Next.js, especially since the parameters of the component are called "pageProps"...
Going to close this in favor of the new methods in #9524.
Most helpful comment
Love the idea of renaming
ComponenttoPage! I think it is much clearer.