generateStaticParams() fetch api twice at build time
Unanswered
Mossyrose gall wasp posted this in #help-forum
Mossyrose gall waspOP
Stumbled double fetching problem when building app, generateStaticParams() are fetching external API twice and its not request memoization, it actually fetch twice from API.
in my case, i have dynamic route that need to fetch randomName external API and it must be static only revalidate once a day (3600).
on build time the console.log actually logged twice the random name on each route which leads to inconsistency showing the value of randomName,
example of the behaviour on browser :
=> on initial load when we visit the url (http://localhost:3000/game/a) , the randomName show
=> it not only fetch twice on page level but as well as the parent layout.
in my case, i have dynamic route that need to fetch randomName external API and it must be static only revalidate once a day (3600).
on build time the console.log actually logged twice the random name on each route which leads to inconsistency showing the value of randomName,
example of the behaviour on browser :
=> on initial load when we visit the url (http://localhost:3000/game/a) , the randomName show
X Value, when navigate to the same url (http://localhost:3000/game/a) using <Link Component it show Y value=> it not only fetch twice on page level but as well as the parent layout.
export const dynamicParams = false;
export const dynamic = 'force-static'
export const revalidate = 3600
//generating path based on game name
export function generateStaticParams() {
return ROUTES.map((e) => ({
game: e.path,
}));
}
export async function GamePage() {
const randomNames = await fetch('randomNameAPIEndpoint')
console.log(randomNames) // this here fetch logged twice when on build
return (<p>{randomNames}</p>)
}29 Replies
@Mossyrose gall wasp Stumbled double fetching problem when building app, **generateStaticParams()** are fetching external API twice and its not request memoization, it actually fetch twice from API.
in my case, i have dynamic route that need to fetch randomName external API and it must be static only revalidate once a day (3600).
on build time the console.log actually logged twice the random name on each route which leads to inconsistency showing the value of randomName,
example of the behaviour on browser :
=> on initial load when we visit the url *(http://localhost:3000/game/a)* , the randomName show `X` Value, when navigate to the same url (http://localhost:3000/game/a) using `<Link` Component it show `Y` value
=> it not only fetch twice on page level but as well as the parent layout.
ts
export const dynamicParams = false;
export const dynamic = 'force-static'
export const revalidate = 3600
//generating path based on game name
export function generateStaticParams() {
return ROUTES.map((e) => ({
game: e.path,
}));
}
export async function GamePage() {
const randomNames = await fetch('randomNameAPIEndpoint')
console.log(randomNames) // this here fetch logged twice when on build
return (<p>{randomNames}</p>)
}
try using react cache to dedup the request
https://react.dev/reference/react/cache#cache-expensive-computation
https://react.dev/reference/react/cache#cache-expensive-computation
@Ray try using react cache to dedup the request
https://react.dev/reference/react/cache#cache-expensive-computation
Mossyrose gall waspOP
i did try that and still it fetch twice
can you show the code
@Ray can you show the code
Mossyrose gall waspOP
import { cache } from "react";
export const dynamicParams = false;
export const dynamic = 'force-static'
export const revalidate = 3600
//generating path based on game name
export function generateStaticParams() {
return ROUTES.map((e) => ({
game: e.path,
}));
}
const getRandomNames = cache(async() => {
await fetch('randomNameAPIEndpoint')
})
export async function GamePage() {
const randomNames = await getRandomNames()
console.log(randomNames) // this here fetch logged twice when on build
return (<p>{randomNames}</p>)
}I just tried myself and it does fetch twice at build time
well not fetching
I just console.log
it run twice
Mossyrose gall waspOP
does the random name still show the same ? at initial load vs navigating using link
yes
you can go to .next/server/app/game/a and see the html content
Mossyrose gall waspOP
at initial load and when navigate to the same path ?
yes
if the page is static generated, you will have a html file at .next/server/app/game/a.html
@Ray if the page is static generated, you will have a html file at .next/server/app/game/a.html
Mossyrose gall waspOP
take a look at .rsc vs .html file inside .next/server/app/game/ it show 2 different value for me
it is different for me too in .rsc and html
Mossyrose gall waspOP
it caused my page show different name between when navigating and first load.
do you mean the name on your page not static? or just initial load is different
oh i can reproduce it now
@Ray do you mean the name on your page not static? or just initial load is different
Mossyrose gall waspOP
page is static, but it looks like have 2 different version,
for example when opening the url (first load) - the name show
for example when opening the url (first load) - the name show
z but when navigating to same page using my navbar and <Link> component the name change into x even both is static page but its like 2 different versioni dont if its a feature or a bug
look like a bug in this case lol
Mossyrose gall waspOP
i have been looking through almost all thread about this issue and no one comes up with the solution, headache.
i think only static export can workaround it for now
Mossyrose gall waspOP
probably, but its still a big problem if its a bug and no solution.
is there a issue for this on github?
Mossyrose gall waspOP
Mossyrose gall waspOP
Probably related https://youtu.be/25yjSzl6PsQ?si=m3sUlIlrmX4oWcW3
Mossyrose gall waspOP
after hours of trial and error i found some workaround / hack to be precise to handle this situation,
basically just create another client component that return null and create useEffect with router.refresh() function and imported inside the page file. this will refresh page and refetch with static generated file.
basically just create another client component that return null and create useEffect with router.refresh() function and imported inside the page file. this will refresh page and refetch with static generated file.