Next.js Discord

Discord Forum

Going in circles trying to cache a server component, nothing seem to work, what am I missing?

Answered
Champagne D’Argent posted this in #help-forum
Open in Discord
Avatar
Champagne D’ArgentOP
Next 15, App router.

In my app/page.tsx I have the following
// Imports...

// I had to have this, otherwise it got an error during build (because it cant do DB calls in build-time I guess)
export const dynamic = "force-dynamic";

// This part I want to control the cache of.
async function getCurrentYear() {
  "use server";
  const year = await database.getCurrentYear();

  if (!year) {
    redirect("/inactive");
  }

  return year;
}

export default async function App() {
  const year = await getCurrentYear();

  return (
    ...JSX


I have two requirements:
1. I want to cache the result of my database call. But I could cache the entire page as well, doesn't matter.
2. I want to be able to invalidate cache on demand


What I have tried so far:

"use cache"
Switched to canary and started using "use cache". That got me into an error that I can't export "force-dynamic", and without force-dynamic I can't build. This API looks the best to me, really wanted it to work

cache flags on fetch
Since I'm not using a fetch, using library that makes db calls (with a fetch I cannot access), this doesn't help me.

export const fetchCache = "force-cache";
Tried with
export const fetchCache = "force-cache";

export const revalidate = 120;

but that didn't seem to do anything.

What am I missing? It feels like such a simple use case.
Answered by Jboncz
Its brand new.... I wouldnt use it. Use unstable_cache.
View full answer

81 Replies

Avatar
Server actions shouldn't be used for getting items
it should only be used for mutations
use API routes for getting items
Avatar
Champagne D’ArgentOP
Huh, I'm pretty sure I followed an example from the docs where they had this exact pattern, an async React component that awaited a data fetching server action
Avatar
And there is no way to cache in server actions, since they're expected to be used for mutations
wait, hold on
Can you send a link
Avatar
Champagne D’ArgentOP
yeah trying to find it again, was a few days ago
https://nextjs.org/docs/app/building-your-application/data-fetching/fetching

The first example here seems to follow the same pattern?
Or is that specific to fetch and not for any async javascript function? 🤔
Avatar
this is not a server action
this is a server component
Avatar
Champagne D’ArgentOP
fair - I might be using the wrong terminology, new to Next! What's the difference between my code and that example? If nothing, is it possible to cache a server component like I want to?
My App is a Server Component (if I got the terminology right 😄 ). I want to either cache the entire server component (with an option to invalidate it) or specifically cache the data awaited in the getCurrentYear method
Avatar
Your code is a server action(indicated by use server), and in docs, its server component
Avatar
Champagne D’ArgentOP
I've tried with both "use server" and without use server, seemed to struggle to find a cache solution still!
Avatar
if you remove use server, it should work fine.
Avatar
Champagne D’ArgentOP
Everything works fine except the possibility to cache the darn thing 😦
So I should rather ask the question:
How do I cache a server component?
(or any data within a server component)
Avatar
just add "use cache" to the top
Avatar
unstable_cache works with server actions
dont tell him that 😂
Isnt that only in canary?
Avatar
Champagne D’ArgentOP
I've tried use cache, never managed tomake it build

"use cache"
Switched to canary and started using "use cache". That got me into an error that I can't export "force-dynamic", and without force-dynamic I can't build. This API looks the best to me, really wanted it to work
yes
Avatar
Its not ready for prime to lol
Avatar
no, its in stable i guess
Avatar
unstable_cache does work with server actions tho
Avatar
that is not a good approach
Avatar
Oh wow, I thought that was only canary, seems premature.
Avatar
IIRC joulev or someone told me server action can't be run in parallel
same, but when I searched it, even I was a lil shocked
Avatar
Correct. They cant
they are meant for mutations and you never want to mutate two things at once from the client.... well not never but
Avatar
Champagne D’ArgentOP
Error: "use cache" is only available with the experimental.dynamicIO config.
👉 👉
CanaryOnlyError: The experimental feature "experimental.dynamicIO" can only be enabled when using the latest canary version of Next.js.
Avatar
Idk if 'use cache' is a better appraoch its still unstable.
Avatar
Champagne D’ArgentOP
This is what I got when I tried the "use cache" way
Avatar
What version of nextjs you using?
Avatar
Champagne D’ArgentOP
"next": "15.0.2",
Avatar
Image
Easy to enable it.
Avatar
Champagne D’ArgentOP
Yep, but it requires canary, as you mentioned
CanaryOnlyError: The experimental feature "experimental.dynamicIO" can only be enabled when using the latest canary version of Next.js.
Avatar
Nope
Avatar
Champagne D’ArgentOP
That's the error I get at least
Avatar
Did you enable it in your config?
Avatar
Champagne D’ArgentOP
 ⚠ Found a change in next.config.mjs. Restarting the server to apply the changes...
C:\Projects\x\node_modules\next\src\server\config.ts:250
      throw new CanaryOnlyError('experimental.dynamicIO')
            ^


CanaryOnlyError: The experimental feature "experimental.dynamicIO" can only be enabled when using the latest canary version of Next.js.
Avatar
Oh that is the error not reading lol
Gotcha, so its not in 15.0.2 but its in the docs weird.
I would just give it a few weeks to hit the stable client.
or update to canary and risk it for the biscuit
Avatar
Champagne D’ArgentOP
Switched to canary and started using "use cache". That got me into an error that I can't export "force-dynamic", and without force-dynamic I can't build. This API looks the best to me, really wanted it to work
Got other issues with "use cache", didn't get it to work there either... Idk if unstable or just me 🙂

but kinda gave up hope on "use cache"
Avatar
Its brand new.... I wouldnt use it. Use unstable_cache.
Answer
Avatar
Champagne D’ArgentOP
Why isnt unstable_cache a good approach?
Avatar
Its a known facotr
Avatar
Not in server actions
In server components, it is
Avatar
Meh, if your using server actions for fetching, you already breaking the rule of thumb, use unstable cache.
Theres nothing inherently wrong with it, besides the fact that you shouldnt be using server actions for fetching data.
Avatar
Champagne D’ArgentOP
I'm not, i just thought I was, got the wrong terminology
git blame = me
Avatar
Oh, then yes use unstable cache
Avatar
export const dynamic = 'force-dynamic'
it should cache it completely until revalidated on demand
Avatar
I go now, your in good hands.
Avatar
Champagne D’ArgentOP
Should force-dynamic do that?
or unstable cache 😄
Avatar
Force dynamic is better option
Avatar
Champagne D’ArgentOP
I'm using force-dynamic already, otherwise I got a build error
Because it can't statically generate a page in build-time that required a database call
which makes sense
but it doesn't look to be caching anything
Avatar
Why?
Oh you’re using it ok
Are you on canary or stable?
Avatar
Champagne D’ArgentOP
rn stable, trying out unstable_cache
const getCachedCurrentYear = unstable_cache(
  async function getCurrentYear() {
    const year = await database.getCurrentYear();

    if (!year) {
      redirect("/inactive");
    }

    return year;
  },
  ["current-year"]
);


Seems to cache it 👍 Haven't tried invalidating, but I would assume that would work too...
Thanks a lot for the guidance!!
Edited the post for searchability