Cache only being applied on one fetch call? Inconsistent cache behavior between fetch() calls
Unanswered
Lesser Goldfinch posted this in #help-forum
Lesser GoldfinchOP
I don't understand. I have to two quasi-identical functions inside my RSC. Both use the fetch api. According to nextJS docs, they both should be cached by default. However, only one of them is cacheing the results.
73 Replies
Lesser GoldfinchOP
When I swap the order of the function calls in my component, it swaps. Then only Cairo is cached and not BuenosAires
Aleutian Tern
I tried your code but couldn't reproduce the issue on Next.js 13.15.4. Which version are you using?
Lesser GoldfinchOP
Hi, I am on latest 13.15.4
Aleutian Tern
well I don't know what could be the cause, did you tried removing the .next folder and building it again ?
Lesser GoldfinchOP
I can try doing that
I’ll try when I can
Lesser GoldfinchOP
Hi @Aleutian Tern , I tried but this didn't work. Here's my full code if you need it:
const getAfricaCairo = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/Africa/Cairo",
);
const africaCairo = (await response.json()) as {
datetime: string;
};
return africaCairo;
};
const getBuenosAires = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/America/Argentina/Buenos_Aires",
);
const buenosAires = (await response.json()) as {
datetime: string;
};
return buenosAires;
};
export default async function Test() {
const africaCairo = await getAfricaCairo();
const buenosAires = await getBuenosAires();
return (
<div className="space-y-4 p-4">
<p className="font-bold">BuenosAires</p> {africaCairo.datetime}
<p className="font-bold">AfricaCairo</p> {buenosAires.datetime}
</div>
);
}Aleutian Tern
I tested your code and worked just fine. I don't really know what could be the cause of this bug on your end. This is really strange.
I don't think this will work, but see if calling the fetch in parallel helps:
const getAfricaCairo = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/Africa/Cairo",
);
const africaCairo = (await response.json()) as {
datetime: string;
};
return africaCairo;
};
const getBuenosAires = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/America/Argentina/Buenos_Aires",
);
const buenosAires = (await response.json()) as {
datetime: string;
};
return buenosAires;
};
export default async function Test() {
const africaCairoR = getAfricaCairo();
const buenosAiresR = getBuenosAires();
const [africaCairo, buenosAires] = await Promise.all([africaCairoR, buenosAiresR])
return (
<div className="space-y-4 p-4">
<p className="font-bold">BuenosAires</p> {africaCairo.datetime}
<p className="font-bold">AfricaCairo</p> {buenosAires.datetime}
</div>
);
}Lesser GoldfinchOP
I actually don't even want to make this work. I just want to understand why it is happening. (I dont care about time in cairo/buenos aires ahah)
fetch is behaving very weirdly
Ok, something else that is strange
Now, when I add cache: "no-store" to ONE of the calls, it starts doing this. not storing both of the fetch calls
Either I am not understanding something, or I found a bug in nextJs
i am interested to know what the outcome of
Promise.all([ the values though (if first is still cached)Lesser GoldfinchOP
Yeah, I tried Promise.all like @Aleutian Tern said. It is working as intended
Both are being cached
Actually, it is cacheing on a new NextJS project I just bootstrapped. My old one is not cacheing
o.O so it is a weird timing of cache?
Lesser GoldfinchOP
I don't know. This doesn't seem to be working as intended
lol you should try with unstable_cache and see if that is also broken like this (only if you want to)
Lesser GoldfinchOP
Should I create an issue on nextjs?]
github
real quick, if you do 2 diferent api urls (diferent domain), does it also
Lesser GoldfinchOP
I could try...
because maybe it is doing the url wrong and causing weirdness
and that would help in bug rep
Lesser GoldfinchOP
Do you know any other api that has some randomnly generated data?
@Lesser Goldfinch Actually, it is cacheing on a new NextJS project I just bootstrapped. My old one is not cacheing
Aleutian Tern
Did you tried removing the node_modules and .next folders and reinstalling everything and build it again ? This is last thing I would suggest before opening an issue. Something is definitely off on you old project.
Lesser GoldfinchOP
Found it https://randomuser.me/api/
I'll try doing that @Aleutian Tern
Lesser GoldfinchOP
Just did that. Deleted node_modules and .next
Same result on my old project:
Buenos Aires being cached, but not cairo
Same result on my old project:
Buenos Aires being cached, but not cairo
Both fetch calls without no-store
My new NextJs project is not behaving like this
My new NextJs project is not behaving like this
New one is cacheing both correctly, but adding no-store on one, like I showed in the video breaks it and both get no-stored
yeah, i think this should be an interesting bug rep, i believe your outcome and they kinda make sense (while being weird)
Lesser GoldfinchOP
My old project is in a turborepo monorepo. But I don't think this should matter
@Lesser Goldfinch New one is cacheing both correctly, but adding no-store on one, like I showed in the video breaks it and both get no-stored
Aleutian Tern
I have a nextjs boostraped here, adding no-store to only one fetch works as intend, only the with no-store are being refeteched each time.
Lesser GoldfinchOP
Wow
Are you using two different urls?
and which system are you using (OS), as they might have weirder mechanics
@Lesser Goldfinch Are you using two different urls?
Aleutian Tern
Yes,
The bug only occurs when using the same url ?
Lesser GoldfinchOP
Can you try two same domains?
Aleutian Tern
Yes one second
Lesser GoldfinchOP
Not same URL. Try same domain
@riský and which system are you using (OS), as they might have weirder mechanics
Lesser GoldfinchOP
Linux
and @Aleutian Tern wbu?
Aleutian Tern
Windows
@Lesser Goldfinch Not same URL. Try same domain
Aleutian Tern
const getAfricaCairo = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/Africa/Cairo"
)
const africaCairo = (await response.json()) as {
datetime: string
}
return africaCairo
}
const getBuenosAires = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/America/Argentina/Buenos_Aires",
{
cache: "no-store",
}
)
const buenosAires = (await response.json()) as {
datetime: string
}
return buenosAires
}
export default async function Test() {
const africaCairo = await getAfricaCairo()
const buenosAires = await getBuenosAires()
return (
<div className="space-y-4 p-4">
<p className="font-bold">BuenosAires</p> {africaCairo.datetime}
<p className="font-bold">AfricaCairo</p> {buenosAires.datetime}
</div>
)
}Worked as intend
Lesser GoldfinchOP
Huh
can you make a codesandbox and ill try it (also that would also use linux)
Lesser GoldfinchOP
Wait @Aleutian Tern , I copy pasted your code and it works now ... ?
As intended
Aleutian Tern
Lesser GoldfinchOP
Yeah, mine is doing the same. Working
Oh, I know
@Aleutian Tern , invert the order of the api calls
Or. swap where the no-store is added
@Aleutian Tern js
const getAfricaCairo = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/Africa/Cairo"
)
const africaCairo = (await response.json()) as {
datetime: string
}
return africaCairo
}
const getBuenosAires = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/America/Argentina/Buenos_Aires",
{
cache: "no-store",
}
)
const buenosAires = (await response.json()) as {
datetime: string
}
return buenosAires
}
export default async function Test() {
const africaCairo = await getAfricaCairo()
const buenosAires = await getBuenosAires()
return (
<div className="space-y-4 p-4">
<p className="font-bold">BuenosAires</p> {africaCairo.datetime}
<p className="font-bold">AfricaCairo</p> {buenosAires.datetime}
</div>
)
}
Worked as intend
also only one of these has
cache: "no-store", (but im guessing you tried other variations)Lesser GoldfinchOP
It seems that the error occurs when one call with
cache: "no-store"is called before the second oneAleutian Tern
Yes, I have tested it with another domain fetch call. It appears that after the first “no-store†fetch, all subsequent fetches in the component will be also “no-storeâ€
Lesser GoldfinchOP
Hummm
Aleutian Tern
Also I didn't find an issue related to this on Github
Lesser GoldfinchOP
Well, regarding the issue on the original video I sent (my initial old project), I am using some reactQueryStreamedHidration, with some other stuff I don't understand wrapping my app with a provider
I'm not sure if this is affecting it. But it shouldn't, because all of the fetch calls are on the server
Lesser GoldfinchOP
Hi @Aleutian Tern could you share your latest code with random user inluded?
Aleutian Tern
Sure
const getAfricaCairo = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/Africa/Cairo"
)
const africaCairo = (await response.json()) as {
datetime: string
}
return africaCairo
}
const getBuenosAires = async () => {
const response = await fetch(
"http://worldtimeapi.org/api/timezone/America/Argentina/Buenos_Aires",
{
cache: "no-store",
}
)
const buenosAires = (await response.json()) as {
datetime: string
}
return buenosAires
}
const getRandomUser = async () => {
const response = await fetch("https://randomuser.me/api/")
const user = (await response.json()) as {
results: {
name: {
first: string
last: string
}
}[]
}
return user.results[0]
}
export default async function Test() {
const buenosAires = await getBuenosAires()
const africaCairo = await getAfricaCairo()
const user = await getRandomUser()
return (
<div className="space-y-4 p-4">
<p className="font-bold">BuenosAires</p> {africaCairo.datetime}
<p className="font-bold">AfricaCairo</p> {buenosAires.datetime}
<p className="font-bold">RandomUser</p>
{user.name.first} {user.name.last}
</div>
)
}Aleutian Tern
I tested changing the fetch options of others to see if the cache option is being respected:
- If you add “force-cache†(which is the default behavior), the fetch returns to its default behavior.
- If you add “no-storeâ€, any subsequent fetch without its cache option defined will now be “no-storeâ€.
- If you add “no-store†to the 1° fetch, and in the 2° fetch you add “force-cacheâ€, the 3° fetch will still behave as if you added “no-storeâ€
The bug seems to be that adding “no-store†makes any subsequent fetch also “no-storeâ€. The workaround is to explicitly define “force-cache†in the fetch if you want to cache the response.
- If you add “force-cache†(which is the default behavior), the fetch returns to its default behavior.
- If you add “no-storeâ€, any subsequent fetch without its cache option defined will now be “no-storeâ€.
- If you add “no-store†to the 1° fetch, and in the 2° fetch you add “force-cacheâ€, the 3° fetch will still behave as if you added “no-storeâ€
The bug seems to be that adding “no-store†makes any subsequent fetch also “no-storeâ€. The workaround is to explicitly define “force-cache†in the fetch if you want to cache the response.
Lesser GoldfinchOP
Thanks. I’ll investigate this more later. And possibly open an issue on GitHub