Next.js Discord

Discord Forum

ISR with firestore in app directory

Answered
Basset Hound posted this in #help-forum
Open in Discord
Basset HoundOP
Hello I am trying to do ISR but the page keeps being SSR

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
View full answer

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.tsx
Basset HoundOP
Sure, will try. One sec
Building still says
λ  (Dynamic)  server-rendered on demand using Node.js
Hmm 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
@Ray why it seem to be doing ISR?
Basset HoundOP
But npm run build still says
λ (Dynamic) server-rendered on demand using Node.js
yes because you didn't have generateStaticParams to tell nextjs generate the page at build time
dynamicParams 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 generateStaticParams
Basset 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 generateStaticParams
when 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.