Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing as Props vs Extracting Cache Apollo Client Nextjs

I posted this in the apollo-client repo, but thought I would ask stackoverflow as well

Hello! I'm new to apollo (and graphql as a whole) and am having some questions about SSR / SSG. I conceptually know what SSR/SSG is and how it works, but not so much with apollo-client.

I've tried searching and scouring the web for which way to do this correctly and have seen both versions with little explanation of why, so my goal with this post to have a place to point and go "This is why you do one over the other".

What are the upsides / downsides between doing

This is a mix of TypeScript and psuedo-code please don't critique syntax kthx

// apolloClient.ts
const client = new ApolloClient({
  link: new HttpLink({ uri: '/graphql' }),
  cache: new InMemoryCache(),
});
// component.tsx
import client from '../apolloClient';

const Component: FunctionalComponent = ({ data }) => {
   ...
}

export const getServerSideProps: GetServerSideProps = async () => {
  const { data } = client.query(...);

  return {
    props: { data }
  }
}
// app.tsx
import client from './client';

const MyApp: NextComponentType<AppContext, AppInitialProps, AppProps> = ({ Component, pageProps }) => (
  <ApolloProvider client={client}>
    <Component {...pageProps} />
  </ApolloProvider>
);

VS

// apolloClient.ts
const createClient = () => new ApolloClient({
  link: new HttpLink({ uri: '/graphql' }),
  cache: new InMemoryCache(),
  ssrMode: typeof window === 'undefined',
});

let client: ApolloClient<NormalizedCacheObject>;
const initalizeApollo = (initalState?: NormalizedCacheObject) => {
  const apolloClient = client ?? createClient();

  if (initalState) {
    apolloClient.cache.restore({
      ...apolloClient.cache.extract(),
      ...initalState,
    });
  }

  if (typeof window === 'undefined') return apolloClient;

  client ??= apolloClient;

  return client;
}

const useApollo = (initalState?: NormalizedCacheObject) => useMemo(() => initalizeApollo(initalState), [initalState]);
// component.tsx
import { useQuery } from 'apollo-client';
import useApollo from '../apolloClient';

const Component = () => {
   const { data } = useQuery(...);
}

export const getServerSideProps: GetServerSideProps = async () => {
  const client = useApollo();

  await client.query(...);

  return {
    props: { initalApolloState: client.cache.extract() }
  }
}
// app.tsx
const MyApp: NextComponentType<AppContext, AppInitialProps, AppProps> = ({ Component, pageProps }) => {
  const client = useApollo(pageProps.initalApolloState);

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

This is my own "I don't understand" portion of this discussion

To me it seems doing it the second way (with SSR?) you're having to run queries twice and write a lot of extra code to get the same effect? What are the performance / safety / any benefits at all to either method.

Thanks!

like image 746
R. Gillie Avatar asked Apr 15 '21 21:04

R. Gillie


People also ask

What are the different ways of fetching data in Apollo client?

Wait, you want me to put my data where!? Figuring out how to configure Apollo Client with Next.js can be a bit confusing. This confusion stems from the fact that there are three ways to fetch and render data: static, server-side, and client-side.

Should I use next JS or Apollo client?

I would definitely still use Next.js regardless of ssr/seo stuff. The framework has still so many benefits, and if you don't need ssr, there's no extra boilerplate at all, just use Apollo client as you usually would.

Why can't I see cached data in pageprops [Apollo_state_prop_name]?

This is because the cached data from that query never makes it into pageProps [APOLLO_STATE_PROP_NAME] (following the official example), since it was executed from a React component rather than from getStaticProps or getServerSideProps.

What is the Apollo client in GraphQL?

The Apollo Client is a state management client that allows you to manage both local and remote data with GraphQL and you can use it to fetch, cache, and modify application data. So, without further ado, let’s get started. First, let’s look at why we should use the Apollo Client with Next.js. There are three key reasons to use the Apollo Client:


Video Answer


1 Answers

Your first approach is more in line with what Next is trying to do. It wants to pull data at build time for pages via getStaticProps (SSG) or getServerSideProps (SSR). The idea is that it will generate pages on the server statically whenever it can.

Apollo Client doesn't need to be referenced in the getStaticProps/getServerSideProps call. I think you could get away with using Context and not even need Apollo Client the way your code is written.

Where I use Apollo in Next apps is when I need to pull data into components. Next doesn't really have an answer for that but it's what Apollo does really well. A good use case is a menu that appears on every page. You don't want to trigger a site-wide static regeneration if you change on menu item. Apollo will keep all the pages fresh and won't trigger Next to render again.

Outline of what I have been doing in this answer.

like image 75
serraosays Avatar answered Nov 08 '22 16:11

serraosays