AO Folts
AO Folts

Reputation: 499

getInitialProps never gets called...what am I doing wrong?

I'm new to React and Next.js, so bear with me. But I've spent three hours searching, and I cannot for the life of me figure out what I'm doing wrong here.

this.props.test doesn't output anything, even though it seems like it should output 'test'.

It's like getInitialProps is never even called.

class Example extends React.Component {

  static async getInitialProps() {
    return {
      test: 'test'
    }
  }

  render() {
    return (
      <h1>Hi {this.props.test}</h1>
    )
 } 

}

Upvotes: 21

Views: 17640

Answers (3)

spatak
spatak

Reputation: 1379

Just remove pages/_app.js file if it's your case.

That happens because _app.js overrides the defaults of NextJS.

If you still want to use getInitialProps along with _app.js you must declare this very function inside _app.js:

Inside _app.js:

export default class MyApp extends App {
 static async getInitialProps(appContext){

  // your logic goes here

  return {}
 }
 
 render(){
  const {Component} = this.props;

  return (
   <Layout>
    <Component />
   </Layout>
  )
 }
}

Upvotes: 0

coblr
coblr

Reputation: 3038

I came here with the same problem, and my Component was in /pages so the other answers didn't really help.

My issue was that I was using a custom App (/pages/_app.js) and it had a getInitialProps in it.

It's a little vague in the documentation, but in the custom app example it does mention (emphasis mine):

Only uncomment [getInitialProps] if you have blocking data requirements for every single page in your application. This disables the ability to perform automatic static optimization, causing every page in your app to be server-side rendered.

This essentially means that if your custom _app.js has a getInitialProps method, you are telling Next.js that this is the only blocking data and every other page component can just be assumed to not have or need their own getInitialProps. If you have one anyway, it'll be ignored and that's where my problem was.

This was solved by calling the getInitialProps on the page component from inside the getInitialProps for the custom App.

// pages/_app.js
const App = ({Component, pageProps }) => (
  <React.Fragment>
    <AppHeader />
    <Component {...pageProps />
  </React.Fragment>
)

App.getInitialProps = async ({Component, ctx}) => {
  let pageProps = {}
  if(Component.getInitialProps){
    pageProps = await Component.getInitialProps(ctx)
  }
  return { pageProps }
}

// pages/home.js
const Home = ({name}) => <div>Hello world, meet {name}!</div>

Home.getInitialProps = async () => {
  return { name: 'Charlie' }
}

export default Home

I'm not sure why you can't return pageProps directly (nothing gets passed), but it seems to be something special and it's working for me now, so..

Upvotes: 38

AO Folts
AO Folts

Reputation: 499

Because getInitialProps only works for Pages in Next.js, the correct method for child components is componentDidMount with setState instead of props.

Upvotes: 25

Related Questions