-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handling Apollo Client Cache Hydration in Next.js 13's app directory #10466
Comments
With @ProchaLu we managed to get the queries done server-side being cached in the frontend, passing the cache to a client component using ApolloProvider You can find an example here: https://stackblitz.com/github/Josehower/next-js-13-with-apollo-cache?file=util%2Fclient.ts // app/page.js => Server Component
export default async function HomePage() {
const client = initializeApollo(null);
await client.query({
query: gql`
// ... query logic
`,
});
return (
<main>
<ApolloClientProvider
initialApolloState={JSON.stringify(client.cache.extract())} // Extract the cache from the server client
>
<Animals />
</ApolloClientProvider>
</main>
);
} // app/ApolloClientProvider.tsx => Client Component
type Props = {
initialApolloState: string;
children: React.ReactNode;
};
export default function ApolloClientProvider(props: Props) {
const apolloClient = useApollo(JSON.parse(props.initialApolloState)); // initialize client with the server cache
return (
<ApolloProvider client={apolloClient}>{props.children}</ApolloProvider>
);
} The way we manage to get the clients synchronised was by extracting the cache server-side and using it to initialize the frontend-side client // used first time on the server with null
export function initializeApollo(
initialState: NormalizedCacheObject | null = null,
) {
const _apolloClient = apolloClient ?? createApolloClient();
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState);
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
// used on ApolloClientProvider Component with the cache extracted on the HomePage Server Component
export function useApollo(initialState: NormalizedCacheObject) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
} There are still things that can be better, and this may need some adaptations to apollo-client #10344 (comment) Unfortunately, not being able to use context on a Server Component is definitely something making our life hard. Similar issues impact Emotion:
|
Hey @Josehower, if I'm reading that code correctly you have to embed your custom ApolloProvider into every page? |
sorry for the late response i was on vacations. Yes every page that need access to the Apollo Client need to use this provider component. I know is a bit annoying but in order to use the Apollo provider you need to have a Client Component. An alternative option would be add the provider on a layout but that means from there all the pages should be client components what is also not nice. Unfortunately this is something that probably need to be addressed by Apollo since the lack of useContext on Server Components has this limitation. |
@Gasheck posted an alternative solution in the main Next.js 13 app directory issue (not sure yet what the downsides are, if there are any): |
Hey everyone, I just wanted to let you all know that we released a package to support React Server Components and the new streaming SSR for Client Components that the Next.js App router offers. You can find the package repository over here: @apollo/experimental-nextjs-app-support I will be closing this issue here and would love it if you could give us feedback and suggestions for improvements over in the other repo! |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
I have a question regarding the Cache Hydration in Next.js 13 since they introduced app/ directory + React server components.
What is the purpose of the
apolloClient.cache.restore()
andapolloClient.extract()
methods in the context of using Apollo Client with Next.js 13's app directory, and is it necessary to use this to get the existing cache loaded during client-side data fetching and restore the cache with the merged data?Here is a link to the Next.js 13 example:
https://github.com/vercel/next.js/blob/84720697e4f00bd77689153f7cf39421be9b1d25/ex[…]mples/api-routes-apollo-server-and-client-auth/apollo/client.js
The text was updated successfully, but these errors were encountered: