NextJS + Apollo: How to get multiple queries on apolloClient.query inside getServerSideProps?

Viewed 1302

I'm currently learning NextJS + Apollo and I've been stuck on a problem. Since getInitialProps is not recommended I'm using getServerSideProps. Here I'm using this code in order to get the props server-side and populate the components:

export async function getServerSideProps() {
  // eslint-disable-next-line no-debugger
  const apolloClient = initializeApollo();

  await apolloClient.query({
    query: GET_BANNER_DATA,
  });

  return addApolloState(apolloClient, {
    props: {},
  });
}

The problem is that getServerSideProps can be used only on pages level and not components. So, I'll have to get props for all the components I use on this page.

How can I do that? Does apolloClient.queryaccept more than one query? Or should I do something to addApolloState function?

The official docs haven't considered this and I couldn't find anything like this on another open-source project.

3 Answers

I think getServerSideprops should only be used for the page itself. However on the page you can include multiple components and have each of them query for their own data client side.

const Page = () => {
  return <Component/>
}

...

const Component = () => {
  // do query here
}

You can combine the queries in one query. Let me give you an example.

query posts($month: Int!) {
  posts(month: $month) {
    id,
    name,
  }
}

query notes($month: Int!) {
  notes(month: $month){
    id,
    name,
  }
}

can be combined into one:

query postsAndNotes($month: Int!) {
  posts(month: $month) {
    id,
    name,
  }
  notes(month: $month){
    id,
    name,
  }
}

Query result will have posts and notes objects.

The way I see it, there are two possible options for solving this. For both of them, you want to make sure that you can import the necessary queries at the page level component. I like to do this by defining the query in the file of the component that uses it, then exporting it so that when pages like the one you describe need it for performance reasons, they can just import it and keep things relatively DRY.

From there, I'm going to make an assumption that the queries are not dependent on one another (i.e. results of one query are fed into the variables of the next).

Solution 1 involves combining the two queries into a single query, and making that request. I haven't figured that out yet.

Solution 2 though, involves leveraging Promises, specifically Promise.all

const query1 = apolloClient.query({
    query: GET_BANNER_DATA,
  });

const query2 = apolloClient.query({
    query: SOME_OTHER_QUERY,
  });

Promise.all([query1, query2]).then(
    (responses) => {
      // Do some manipulation of the data responses
    }
  );

return addApolloState(apolloClient, {
    // You'll pass whatever props you need for the page to render here,
    // but shouldn't need to do anything for the sub-components.
    // When they go to make their queries, the data will already be in the local Apollo cache
    props: {},
  });
Related