简体   繁体   中英

Next.js - understanding getInitialProps

I have an app that uses next.js along with Apollo/ Graphql and i'm trying to fully understand how the getInitialProps lifecycle hook works.

The lifecycle getInitialProps in my understanding is used to set some initial props that will render server side for when the app first loads which can be used prefetch data from a database in order to help SEO or simply to enhance page load time.

My question is this:

Every time I have a query component that fetches some data in my components across my app, do I have to use getInitialProps to be sure that data will be rendered server side?

My understanding is also that getInitialProps will only work in the page index components (as well as in _app.js ), this would mean that any component lower down in the component tree would not have access to this lifecycle and would need to get some initial props from way up at the page level and then have them passed down the component tree. (would be great if someone could confirm this assumption)

Here is my code:

_app.js (in /pages folder)

import App, { Container } from 'next/app';
import { ApolloProvider } from 'react-apollo';

class AppComponent extends App {
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {};
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    // this exposes the query to the user
    pageProps.query = ctx.query;
    return { pageProps };
  }
  render() {
    const { Component, apollo, pageProps } = this.props;

    return (
      <Container>
        <ApolloProvider client={apollo}> 
          <Component client={client} {...pageProps} />               
        </ApolloProvider>
      </Container>
    );
  }
}

export default AppComponent;

Index.js (in /pages/users folder)

import React, { PureComponent } from 'react';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';

const USERS_QUERY = gql`
  query USERS_QUERY {
    users {
      id
      firstName
    } 
  }
`;

class Index extends PureComponent {
  render() {
    return (
      <Query query={USERS_QUERY}>
        {({data}) => {
          return data.map(user => <div>{user.firstName}</div>);
        }}
      </Query>
    );
  }
}

export default Index;

The answer is NO

If you use Apollo with Next JS you will not have to use getInitialProps on each page to get some initial data rendered server side. The following configuration for getInitialProps is enough for all the components to render out with their respective queries if they have <Query> components in them

static async getInitialProps({ Component, ctx }) {
    let pageProps = {};
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }
    // this exposes the query to the user
    pageProps.query = ctx.query;
    return { pageProps };
  }

My issue and why I wasnt seeing any server side rendering is that Heroku or Now wouldnt perform SSR with a public URL ie my-app.heroku.com. To resolve this I purchased and applied a custom URL in Heroku and it worked. Along with a custom URL I had the following configuration in my Apollo config

  const request = (operation) => {
    operation.setContext({
      fetchOptions: {
        credentials: 'include'
      },
      headers: { cookie: headers.cookie }
    });
  }; 

This completely resolved it and now I have SSR without the pain of having to manually set getInitialProps on each page

Hope this helps someone

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM