draftMode disables cache so hard, that memoization is also skipped #91915
Replies: 4 comments 10 replies
-
|
I think the behavior you are seeing is consistent with how Next splits caching layers.
So if your feature flags endpoint is being hit 100 times in draft mode, it usually means one of these:
If your goal is "fresh every request, but deduped within that request", I would not rely on import { cache } from 'react'
const getFlags = cache(async () => {
const res = await fetch('https://flags.example.com/api/flags', {
cache: 'no-store',
})
if (!res.ok) throw new Error('Failed to load flags')
return res.json()
})or fetch once at the page/layout boundary and pass the result down. That gives you:
Relevant docs:
So short version: yes, draft mode disables the persistent cache on purpose. If you still want per-request dedupe, use |
Beta Was this translation helpful? Give feedback.
-
|
The issue is that When The fix: switch to import { cache } from 'react';
export default cache(async function getContentTypes() {
const apiUrl = 'https://strapi.example.com/api';
const apiToken = 'example';
const res = await fetch(`${apiUrl}/content-type-builder/content-types`, {
cache: 'no-store', // <-- change this
headers: {
Authorization: `bearer ${apiToken}`,
},
});
const result = await res.json();
return result.data;
});The reasoning: For your Strapi draft/published use case specifically, you can also pass import { cache } from 'react';
import { draftMode } from 'next/headers';
export const getContentTypes = cache(async function (isDraft: boolean) {
const res = await fetch(
`https://strapi.example.com/api/content-type-builder/content-types?status=${isDraft ? 'draft' : 'published'}`,
{
cache: 'no-store',
headers: { Authorization: `bearer example` },
}
);
return (await res.json()).data;
});
// In your page/layout:
const { isEnabled } = await draftMode();
const data = await getContentTypes(isEnabled); // deduped per render passThis gives you fresh data every request in draft mode, with full deduplication within the render pass. |
Beta Was this translation helpful? Give feedback.
-
|
@laurenskling - sorry I was out last week, and spammers took over... Could this be the issue? The spam makes it a bit annoying to parse what's been said here, but I do believe your getContentTypes function access headers/cookies? |
Beta Was this translation helpful? Give feedback.
-
|
@laurenskling You’ve hit on a subtle but important distinction: cache invalidation vs. memoization. Right now, in
In practice, it often makes sense to skip caching in draft mode (so you always see fresh data), but still keep memoization active (so you don’t re‑fetch the same resource dozens of times during one render). Why memoization should remain
Possible approaches
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I wrap my fetch calls in a "use cache" and can call them from anywhere in my code (for example to check feature flags for other fetch calls), and the memoization only calls this data once.
Now when I run in draftMode, not only all caches are skipped (good), also memoization is skipped. So my feature flags endpoint gets 100 calls every page load.
Wouldn't it make more sense that the data is freshly requested, but the calls are still memoized?
Beta Was this translation helpful? Give feedback.
All reactions