apollographql / apollo-client-nextjs

Apollo Client support for the Next.js App Router
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support
MIT License
436 stars 32 forks source link

Can't create a client per page #322

Closed JCB-K closed 2 months ago

JCB-K commented 2 months ago

I'm not sure if this is a bug or a user error, but I can't wrap 2 different pages in 2 different GraphQL providers with respective clients, as makeClient is not called a subsequent time after navigating from page 1 to 2.

I've created a sandbox here that demonstrates the problem: https://codesandbox.io/p/devbox/kind-tristan-jnk964

Is this a bug, or do I misunderstand how the provider should work?

phryneas commented 2 months ago

You should only ever have one ApolloClient instance - and one provider - in your application.

This is a restriction we have here because your page will run in SSR, and if you had multiple providers we wouldn't know which data should be rehydrated with which client instance. But apart from that, it's also generally a good rule of thumb ;)

Just place your NextApolloProvider in your root layout. You don't need one per page.

JCB-K commented 2 months ago

@phryneas In that case, how would I switch client between pages? The layout doesn't re-render on page navigation.

phryneas commented 2 months ago

You should never switch the client. Why do you want to do that?

JCB-K commented 2 months ago

I have 2 applications within the same Next.js app that communicate with different graphql servers. As of now I don't have the control to merge these into a single GQL endpoint.

phryneas commented 2 months ago

Ah, that's indeed one of the very rare cases where that might make sense.

You could call resetApolloClientSingletons when your page renders, that would clear any old globally stored ApolloClient instance.

import { resetApolloClientSingletons } from "@apollo/experimental-nextjs-app-support";
JCB-K commented 2 months ago

That worked great, thanks! For future reference for those reading this issue: you want call resetApolloClientSingletons whenever the client changes. In my case I found it most natural to do so in ApolloWrapper:

export function ApolloWrapper({
  children,
  client,
}: React.PropsWithChildren<{ client: "a" | "b" }>) {
  React.useEffect(() => {
    resetApolloClientSingletons();
  }, [client]);
  return (
    <ApolloNextAppProvider makeClient={getMakeClient(client)}>
      {children}
    </ApolloNextAppProvider>
  );
}
github-actions[bot] commented 2 months ago

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.