2

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.

eripanci
  • 25
  • 1
  • 5

3 Answers3

0

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
}
  • 1. This means that I should put all my components in a single file. If so, this is a bad idea, right? 2. Even if I do this, I believe I can only use `getServerSideProps` once and my initial problem is still there. 3. I've mentioned Apollo in the title, so please I would love to get an answer with Apollo functions in it. I know how to do it with other methods (fetch, etc) but I can't seem to find an answer with this. Thanks nonetheless! – eripanci Aug 03 '21 at 13:30
  • 1. No you can create components anywhere you want and import them, you don't need to create them in the same file. 2. Your initial problem isn't still there and forget about getServerSideProps, it's irrelevant, just use the components for your use case. 3. You can use useQuery(Query) or client.query in each component, if you want to know how apollo works then make a new question. Forget about trying to get props server side, get your data client side. –  Aug 03 '21 at 13:33
  • 1. Yes, I can import them but I can't do the query on export (or will be complicated to do so). 2. No, I need `getServerSideProps`, because I have to render the page on the server-side for SEO purposes. I know how to do this only on the client side. 3. The same thing as point 2. I know that I can use `useQuery(Query)` inside a component, but I wanted to know how to do this process on server-side. – eripanci Aug 03 '21 at 13:53
0

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.

Erkin Kurt
  • 652
  • 6
  • 16
  • I don't think this is a solution in my case. I've got the queries separated for each component and given a variable; that's why you see "GET_BANNER_DATA" in my case and not a query. Can I do this why with variables? – eripanci Aug 03 '21 at 13:15
  • I understand your point. To run this on getServerSideProps you need to fetch everything and pass them to your components unless you do not consider client side fetching. Create one query that fetches all the data you want. If the other queries that you have depends on some parameters you need to figure out your call order and architecture. – Erkin Kurt Aug 03 '21 at 13:32
0

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: {},
  });
alanmoo
  • 1,105
  • 1
  • 7
  • 8