Skip to content
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

is it possible that a client component query can used cached response from server component query? #326

Closed
kimvuVarner opened this issue Jul 1, 2024 · 6 comments

Comments

@kimvuVarner
Copy link

kimvuVarner commented Jul 1, 2024

Hello!, this is more of a cry for help rather than a issue. But I don't really know where else to ask

I currently have a nextjs + apollograph built upon the pages directory, but want to migrate to the new app directory with app routing. The issue I have is that I don't really find a way to use the ApolloNextAppProvider together with the registerApolloClient. The main issue: In the old way we did a serverside request called useFramework(), that had framework related global states and so on. Then on clientside we used the same request, but now fetched through the apollo-cache so that we didn't get unnecessary requests on.

Now I try to implement this in a very simple POC:
this is a server component that fetches the Framework-data, StartPage is a client side component. So everything down the line from StartPage will be clientside. How can i use the same query in a client component in order to use the cached response?

import React from 'react';
import { headers } from 'next/headers';

import { StartPage } from '@pages/sales/StartPage';
import { FrameworkDocument } from '@schema-types';
import { getClient } from '@lib/RSCClient';
const Home = async () => {
  const headersList = headers();
  const domain = headersList.get('host') || '';
  const fullUrl = headersList.get('referer') || '';
  const relativeUrl = fullUrl.split(domain)[1];
  const client = getClient();
  const { data, error } = await client.query({
    query: FrameworkDocument,
    variables: {
      url: relativeUrl,
    },
  });
  return <StartPage data={data} />;
};
export default Home;

I've tried using ApolloNextAppProvider in order to make the client requests work, but then I think I'll get two seperate clients, which I don't want, because the don't share same cache

Are a possible solution to store the framework data in a context? and wrap the context around everything in layout.tsx? or maybe pass data down from the server component?

Tasks

No tasks being tracked yet.
@kimvuVarner kimvuVarner changed the title Use ApolloNextAppProvider with registerApolloClient together is it possible that a client component query can used cached response from server component query? Jul 1, 2024
@phryneas
Copy link
Member

phryneas commented Jul 1, 2024

I think I'll get two seperate clients, which I don't want, because the don't share same cache

Yes, and that will always be the case - RSC and SSR of Client Components (and later, the browser) run in different processes, sometimes even on different machines at different times. You can share nothing between them, and you should never use the same query in a RSC component and a Client Component. If the cache value updated, the static RSC HTML would not update while the Client Component would update the value - you'd get inconsistent UI.

That's why this is one of the first paragraphs of our README:

❗️ We do handle "RSC" and "SSR" use cases as completely separate.
You should generally try not to have overlapping queries between the two, as all queries made in SSR can dynamically update in the browser as the cache updates (e.g. from a mutation or another query), but queries made in RSC will not be updated in the browser - for that purpose, the full page would need to rerender. As a result, any overlapping data would result in inconsistencies in your UI.
So decide for yourself, which queries you want to make in RSC and which in SSR, and don't have them overlap.

You can use <PreloadQuery in a RSC context to preload data that you want to later display in a Client component, but you should only use that for preloading - after that, you should consider that data as "client data" and never display it in a RSC component.

In the end, you should decide for every piece of data in your application if you only show it in server components, or only in client components.

@kimvuVarner
Copy link
Author

kimvuVarner commented Jul 2, 2024

Thanks for the quick response! So never share data between RSC and Client Component only preload.

I have another question regarding the initialization of Apollo client. In our current codebase we have used this guide for our SSR logic: https://medium.com/@zhamdi/server-side-rendering-ssr-using-apollo-and-next-js-ac0b2e3ea461. We have a bunch of function like: initializeApollo(), useApollo(), createApolloClient() and I can't see how they'll fit in the new app router. How do I start to migrate all the apollo-functionality we've built using this guide? Or is this something that isn't necessary anymore? Or is this exactly what <PreloadQuery> does? I know its kind of a big question, and I don't expect to get the whole answer. But this is our goal now: to migrate all this logic into the app directory, so I'll take any tips I get :)

@phryneas
Copy link
Member

phryneas commented Jul 2, 2024

All of that isn't necessary anymore - it's essentially what this package does (although, due to the new streaming SSR model of the App router in a much more complicated fashion ;) ).

Just follow our README and you will be set up!

@kimvuVarner
Copy link
Author

Allright, thanks!

@phryneas
Copy link
Member

phryneas commented Jul 2, 2024

I believe everything here has been answered, so I'll close the issue :)

If you have any more questions in the future, feel free to open another issue!

@phryneas phryneas closed this as completed Jul 2, 2024
Copy link

github-actions bot commented Jul 2, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants