Determine if RSC is being invoked by client side navigation or initial page load
Unanswered
Brown bear posted this in #help-forum
Brown bearOP
I have a dynamic endpoint:
However, on subsequent hits to a
How can I determine wihtin a react server component, if the request was made by client side navigation or if its an initial page load?
/users/[id]
. If someone hard navigates to the page, I want the server component to fetch the data. This works great. I have a server component that gets the id from the url and awaits the results and uses it to paint the initial render with data.However, on subsequent hits to a
/users/[id]
page I want to rely purely on client side data fetching. It has the added benefit of potentially cacheing data, and I don't want to accidentally refetch data because the server does not know about the client cache. How can I determine wihtin a react server component, if the request was made by client side navigation or if its an initial page load?
7 Replies
Brown bearOP
Bumping this for further information.
Brown bearOP
For further info: Imagine I am navigating between to views that ultimately have some shared fetched data. If I do this entirely client side, its free, because of react-querie's inherit cacheing. But if I am forced to go through the normal servercomponent fetch process the server will fetch the data again because it has no context on what the client knows.
I basically need a mechanism to determine if the server component is being run because of a client side navigation, or because of an initial page load so I can skip the fetch if its the former.
Edit: Though this doesn't appear documented anywhere, cleint side navigation seems to send the
I basically need a mechanism to determine if the server component is being run because of a client side navigation, or because of an initial page load so I can skip the fetch if its the former.
Edit: Though this doesn't appear documented anywhere, cleint side navigation seems to send the
accept
header */*
whereas initial load navigation sends text/html
. I have no idea how robust this is and do not consider it proven and reliable solution but does seem to be working for now. Would still like more feedback from others more knowledgeable or the team itself"However, on subsequent hits to a /users/[id] page I want to rely purely on client side data fetching. "
Subsequent hits will be cached by the browser for a short period of time. Why do you need the subsequent hit to be a client component?
When you use the <Link /> component, Next will fetch the dynamic page if the data has changed. (or i think that's how it worked in v14)
It sounds like you should just cache the route, to prevent refetching.
Subsequent hits will be cached by the browser for a short period of time. Why do you need the subsequent hit to be a client component?
When you use the <Link /> component, Next will fetch the dynamic page if the data has changed. (or i think that's how it worked in v14)
It sounds like you should just cache the route, to prevent refetching.
Brown bearOP
But that still means the route itself will potentially refetch data the client already knows.
Imagine a situation like this:
I have two complex pages, While they are different routes
On the backedn page RSC async component for both
I am relatively new to nextjs but this seems like a pretty standard problem. I don't want to pre-emptively fetch or cache this data ahead of time because its very expensive to run, so I onlny want it run when it needs to be which would be on initial load.
Asssuming I did want to do what you are positing, how would I do that? I am strugglign to figure out how to make nextjs cache a very dynamic route with very dyanmic parameters outside the uri (we use search params thrown into cookies so a layout component has access to them, which is anti-pattern but was another glaring omision by nextjs)
Imagine a situation like this:
I have two complex pages, While they are different routes
/foo
and /bar
there is one incredibly complex and time consuming query shared between them, and this query is complex and determined by state or query parameters but not a uri slug. On the backedn page RSC async component for both
/foo
and /bar
it will prefetch the queries to hydrate the react-query client in both components with hte initial data for fast loads. However if I navigate from /foo
to /bar
via client side navigation, /bar
will still hit the RSC with the same parameters /foo
already fetched, and will return /bar
after the query completes. If I knew this was happening due to client side navigation and not initial page load, I could skip the fetch in /bar
because I know on the client it would have the cached data from /foo
I am relatively new to nextjs but this seems like a pretty standard problem. I don't want to pre-emptively fetch or cache this data ahead of time because its very expensive to run, so I onlny want it run when it needs to be which would be on initial load.
Asssuming I did want to do what you are positing, how would I do that? I am strugglign to figure out how to make nextjs cache a very dynamic route with very dyanmic parameters outside the uri (we use search params thrown into cookies so a layout component has access to them, which is anti-pattern but was another glaring omision by nextjs)
If the route is cached, then no, it won't refetch the data, it will use the locally cached data - therefore it'll be pretty much instant. What eversion of Next are you using?
Brown bearOP
I don't understand how the route could be cached though. In the case of traversing from
I am on 15.2
Edit: Oh I am looking at this data cache path. I see, interesting... Is this: https://nextjs.org/docs/app/building-your-application/caching#data-cache What you mean then by cacheing? Not cacheing the component but hte request itself?
Fiddling with this a bit, it still raises a concern. Sure if I hard load
I wonder if I use a sort of middleware route.ts GET endpoint that hits the api and returns it to the client, if we would get best of both worlds. The problem is I am now proxying to the server to get the API request instead of going straight to it from the client. The vercel deploy is co-located physically wiht the api server so maybe the loss is meaningless, and I think this would give us client side and server side cacheing...
/foo
to /bar
the data is the same but having never to be /bar
with this spefcific set of parameters there is no cache for /bar
? I am on 15.2
Edit: Oh I am looking at this data cache path. I see, interesting... Is this: https://nextjs.org/docs/app/building-your-application/caching#data-cache What you mean then by cacheing? Not cacheing the component but hte request itself?
Fiddling with this a bit, it still raises a concern. Sure if I hard load
/foo?param=test
such that we load fetch for test
on the server with cacheing, that hten, it is loaded appropriately in the server cache, and as such /bar?param=test
the problem is, if I hard load /foo?param=test
but then client side route to /foo?param=test2
and the swtich to /bar?param=test2
it won't instantly load because the server doesn't have hte cahce of test2
only the client does...I wonder if I use a sort of middleware route.ts GET endpoint that hits the api and returns it to the client, if we would get best of both worlds. The problem is I am now proxying to the server to get the API request instead of going straight to it from the client. The vercel deploy is co-located physically wiht the api server so maybe the loss is meaningless, and I think this would give us client side and server side cacheing...
Brown bearOP
For the record, using the data cacheing as you suggest, and running my request through a route so the data is simulatenously cached on the backend, seems to be working