ISR with firestore in app directory
Answered
Basset Hound posted this in #help-forum
Basset HoundOP
Hello I am trying to do ISR but the page keeps being SSR
Does anyone know why?
According to the docs export const revalidate would apply to all functions in this file
I use the app directory and can't use fetch because I get this data directly from firestore.
I also tried moving export const revalidate = 600; to the page.tsx but that didnt do it either
export const revalidate = 600;
export async function getLeaderboard(role: string) {
const sortField = role === 'teacher' ? 'tasksCreated' : 'timeSpend';
const userQuery = await db
.collection('users')
.where('role', '==', role)
.orderBy('role', 'asc')
.orderBy(sortField, 'desc')
.limit(10)
.get();
console.log('Triggered db call');
const users: User[] = userQuery.docs.map((doc) => doc.data() as User);
return users;Does anyone know why?
According to the docs export const revalidate would apply to all functions in this file
I use the app directory and can't use fetch because I get this data directly from firestore.
I also tried moving export const revalidate = 600; to the page.tsx but that didnt do it either
Answered by Ray
generateStaticParams is not getStaticPaths, generateStaticParams return a list of key
55 Replies
Basset HoundOP
The code provided is getLeaderboard.ts which is in my lib/ the page component which has the revalidate as well uses this.
can you show the code in the page component?
@Ray is this the page component?
Basset HoundOP
So page.tsx contains <BuildLeaderboard> which contains getLeaderboard
have you used
headers(), cookies() or searchParams in the page component?Basset HoundOP
page.tsx
import BuildLeaderboard from './buildLeaderboard';
import Link from 'next/link';
export const revalidate = 600;
export default function Leaderboard({
params: { role = ['student'] },
}: {
params: { role: string | string[] };
}) {
role = Array.isArray(role) ? role[0] : role;
const roles = ['student', 'teacher'];
return (
...
</div>
<BuildLeaderboard role={role} />
</div>
</div>
);
}buildLeaderboard.tsx
import BoardItem from './boardItem';
import { getLeaderboard } from '@/lib/getLeaderboard';
interface Props {
role: string;
}
export default async function buildLeaderboard({ role }: Props) {
const leaderboard = await getLeaderboard(role);
return (
...
);
}@Ray have you used `headers()`, `cookies()` or `searchParams` in the page component?
Basset HoundOP
Nope purely requesting from firebase. Its currently SSR according to my testing and what it says during build
try put
export const dynamicParams = true in the page.tsxBasset HoundOP
Sure, will try. One sec
Building still says
λ (Dynamic) server-rendered on demand using Node.jsHmm weird, db changes doesnt seem to be reflected directly tho. So something went right, but nextjs still thinks its SSR.
always put this in the page.tsx
export function generateStaticParams() {
return [];
}@Ray always put this in the page.tsx
ts
export function generateStaticParams() {
return [];
}
Basset HoundOP
I use the app directory, I used to have this before migrating to page
this is for app router
Basset HoundOP
Oh sorry misunderstood
I dont understand the place generateStaticParams has in my code, it seems like getLeaderboard already does what generateStaticParams is supposed to do. Should i renmae getLeaderboard to generateStaticParams and move it from /lib/getLeaderboard.ts to the page.tsx?
yes
nextjs use the return value from generateStaticParams to generate the page
Basset HoundOP
Ah I see, thanks!
so this should be something like this
export function generateStaticParams() {
return [{ role: "student" }, { role: "teacher" }];
}role is the key params
Basset HoundOP
Its quite weird tho, because with the current setup it seems to be doing ISR except nextjs thinks its SSR.
Basset HoundOP
Well, after adding export const dynamicParams = true;
The db request isnt triggered anymore after the first request, after a minute has passed, it gets triggered again
The db request isnt triggered anymore after the first request, after a minute has passed, it gets triggered again
@Ray why it seem to be doing ISR?
Basset HoundOP
But npm run build still says
λ (Dynamic) server-rendered on demand using Node.js
λ (Dynamic) server-rendered on demand using Node.js
yes because you didn't have
generateStaticParams to tell nextjs generate the page at build timedynamicParams will tell nextjs to generate on demand
and will regenerate if you have export const revalidate
Basset HoundOP
Make sense, I am just a little confused by this situation, because export const dynamicParams should be true by default. So that the funcionality works now is weird.
Is that because
dynamicParams is only set to true if nextjs finds generateStaticParamsBasset HoundOP
Ah okay, thank you very much. I will try this and let you know how it went
look like dynamicParams only work when you have
generateStaticParamswhen you have
generateStaticParams, then dynamicParams will be default to true@Ray when you have `generateStaticParams`, then dynamicParams will be default to true
Basset HoundOP
I couldnt manage it. I got it working again with pages
export async function generateStaticParams(context: any) {
const role = context.params.role || 'student';
const leaderboard = await getLeaderboard(role);
return {
props: {
params: { role },
leaderboard,
},
revalidate: 60,
};
}
export default function Leaderboard({
params: { role = ['student'] },
leaderboard,
}: {
params: { role: string | string[] };
leaderboard: User[];
}) {But whenever I switch to generateStaticParams I cant take context anymore which means I cant know which role this is about
generateStaticParams is not getStaticPaths, generateStaticParams return a list of key
Answer
Basset HoundOP
Ah yeah
Youre right
I totally misread the documentation
sorry for the time waste haha
lol
Basset HoundOP
Got it working now
nice
Basset HoundOP
For some reason during build it says â— (SSG) prerendered as static HTML (uses getStaticProps) tho
Eventhough It should say ISR
Cuz it revalidates after 60 seconds
But I think it always says that
yes
it fine
Basset HoundOP
Awesome, thank you Ray!
@Basset Hound Awesome, thank you Ray!
np please mark solutions.