Next.js Discord

Discord Forum

How to fetch from a GET Route Handler inside a server component?

Answered
Australian Stumpy Tail Cattle Do… posted this in #help-forum
Open in Discord
Australian Stumpy Tail Cattle DogOP
I have a page.tsx (rsc) that fetches the data using fetch call to my own route handler.

So, why not fetch directly from db?

Multiple type of users land on this page, 1. Not logged in, 2. Owners(creators of this page).

The issue is I want to use fetch requests such that the data remains cached, and I can use revalidatePath(in a server action), to revalidate this route handler when the creator updates the page. So it re-fetches the data the next time the page loads.

It seems to work in local dev, but gives me SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON , in vercel logs in dev, when I request the page.

Is there a work around?

Also I am doing all this so as to have the option to use revalidatePath instead of setting fixed time based cache timeout.

Please help me.
Answered by joulev
no, dont fetch your own api routes.

use unstable_cache to cache the db query.
View full answer

20 Replies

Answer
@joulev no, dont fetch your own api routes. use unstable_cache to cache the db query.
Australian Stumpy Tail Cattle DogOP
Thanks a lot for your reply.
Could you tell me if,

const getCachedUser = unstable_cache(
async () => {
return { id: params.userId }
},
[params.userId], // add the user ID to the cache key
{
tags: ['users'],
revalidate: 60,
}
)

let's say the caching of the page depends on the slug, and I pass the slug to the function inside the unstable cache function (like params.userId in the above case).
How do I call the revalidate function (revalidateTag/ revalidatePath) to get this function to reevaluate on demand.

Thanks!!
@joulev revalidateTag("users")
Australian Stumpy Tail Cattle DogOP
But wouldnt that mean that this function will re evaluate for all the pages that are of type repo/[id], instead of just repo/[the particular id for which I want it to reevaluate] page.

repo is REST nomenclature based entity, for all such pages
Australian Stumpy Tail Cattle DogOP
oh great!
Thankyou!!!
so unstable_cache creates different caches for different function evaluations and reevaluates for the one with which the tag(s) match
yeah different tags different cache entries, test:hello and test:world are different, independent tags despite being generated from the same unstable_cache call
don't be afraid of the unstable label, im using it in prod and it's more stable than plenty of supposedly stable nextjs features
@joulev don't be afraid of the `unstable` label, im using it in prod and it's more stable than plenty of supposedly stable nextjs features
Australian Stumpy Tail Cattle DogOP
I just thought it would reevaluate for all the ids for some reason.
I had read that using fetch in rsc is bad idea for own route handlers, but I just didnt know that cache entries are different while using unstable_cache.

Thanks a lot!! Helped a lot!!
@Australian Stumpy Tail Cattle Dog I just thought it would reevaluate for all the ids for some reason. I had read that using fetch in rsc is bad idea for own route handlers, but I just didnt know that cache entries are different while using unstable_cache. Thanks a lot!! Helped a lot!!
i encourage you to play a bit more with unstable_cache, it's really powerful! it's a bit hard to use but once you get the hinge of it you can pretty much cache anything, even user-specific auth-locked data
@joulev i encourage you to play a bit more with unstable_cache, it's really powerful! it's a bit hard to use but once you get the hinge of it you can pretty much cache anything, even user-specific auth-locked data
Australian Stumpy Tail Cattle DogOP
I am meaning to do exactly that "user-specific auth-locked data".

1. So first there is a basic version of the repo, that is created by the owner for all users to see.

2. Then there are logged in users, which have there own metadata on top of the repo, which will be another unstable_cache call. [with repo_id-user_id both in the same tag]

I will now try to do both with unstable_cache.
Also, i guess yes but, we can use an unstable_cached function within an unstable_cached function right? like api routes within routes
@Australian Stumpy Tail Cattle Dog I am meaning to do exactly that "user-specific auth-locked data". 1. So first there is a basic version of the repo, that is created by the owner for all users to see. 2. Then there are logged in users, which have there own metadata on top of the repo, which will be another unstable_cache call. [with repo_id-user_id both in the same tag] I will now try to do both with unstable_cache. Also, i guess yes but, we can use an unstable_cached function within an unstable_cached function right? like api routes within routes
I will now try to do both with unstable_cache.
yeah the general idea is
const cachedData = unstable_cache(...);
// you cannot check auth state inside unstable_cache
// but then you can always check auth before running the function
if (isLoggedIn())
  return cachedData()
else
  redirect("/login")


we can use an unstable_cached function within an unstable_cached function right
i think so, though i'm not 100% sure, you should experiment with it
looking forward to the good news
Australian Stumpy Tail Cattle DogOP
Hey joulev, I forgot to update, it worked!, although I am yet to check it completely as some work came up.

I am using one cached function (cf1) inside another (cf2).
I added the tags of cf1 in cf2 as well to reevalue cf2 as well if cf1 is reevaluated (based on cf1's tag), I am yet to check the performance of this approach as reevaluating cf1 would trigger cf2 revalidations as well which might put some load.

Not sure, if nextjs14 marks the cache entries as invalid on revalidation and reevaluates once requested again, or does it reevaluate immediately on revalidation.

Will have to check. Thanks!