How can I use getInitialProps only during the NextJS site build?
I found the workaround with NextJs 9.0.3 (other versions may also work, I didn't test that)
// XXXPage is your page
XXXPage.getInitialProps = async (req) => {
if (process.browser) {
return __NEXT_DATA__.props.pageProps;
}
// original logic
}
For version 9.3 or newer, it's recommended that you use getStaticProps
for providing static build props.
export async function getStaticProps(context) {
return {
props: {}, // will be passed to the page component as props
}
}
Old answer
There are two ways is one way that I've found to prevent code in getInitialProps
from running on a page component load.
1. Use a regular anchor tag without next/link
to that page.
getInitialProps
only runs when the page is linked from a next/link
component. If a regular JSX anchor <a href="/my-page">click me</a>
is used instead, the component's getInitialProps
will not be invoked. Direct page loads to NextJS static site pages will not invoke getInitialProps
.
Note that using a standard anchor instead of the next/link
component will cause a full page refresh.
Because this is a poor solution, I've submitted a feature request.
2. Use req
in the context
argument to conditionally make the API call in getInitialProps
.
req
in the context
argument to conditionally make the API call in getInitialProps
.I believe what @evgenifotia wanted to convey is that req
is undefined in a site that's been exported.
// example usage of API call in getInitialProps
import fetch from 'isomorphic-unfetch'
function Page({ stars }) {
return <div>Next stars: {stars}</div>
}
Page.getInitialProps = async (ctx) => {
const { req } = ctx // context object: { req, res, pathname, query, asPath }
if (req) { // will only run during the build (next export)
const res = await fetch('https://api.github.com/repos/zeit/next.js')
const json = await res.json()
return { stars: json.stargazers_count }
}
return {}
}
export default Page
For more information about getInitialProps
, see the documentation. One example there confirms that req
is expected to only be defined on the server (or during the exporting build):
const userAgent = req ? req.headers['user-agent'] : navigator.userAgent`
This second option may work for some scenarios, but not mine where returning an empty result from getInitialProps
will affect the component's this.props
.
Note:
Shallow routing is not the answer. According to the documentation (see under "Notes" section):
Shallow routing works only for same page URL changes.