getStaticPaths vs getStaticProps vs generateStaticParams
Answered
Airedale Terrier posted this in #help-forum
Airedale TerrierOP
Hi I am trying to understand when to use which method for generating dynamic routes. I have a notes taking app that renders staticaly generated web pages (export: true) with dynamic routes
I have two pages with dynamic routes :
My requirement is that when I publish a log it should be saved to both local and firebase and when fetched it should be fetched only from localStorage on routes with
I looked at the documentation from nextJS and it seems to suggest to use
The data comes from a database
But, It also reads
Some guidance on what is the best choice for my requirement would be really helpful.
Thanks
I have two pages with dynamic routes :
pastelog/src/app/(main)/logs/[id]/page.tsx
pastelog/src/app/(publish)/logs/publish/[id] /page.tsxfetchLogs is basically calling a method from firestore and fetching the document id, The app works fine, But I would like to integrate local Storgae, but as soon as I replace that method with fetching logs from local Storage I get the below error⨯ Error: Page "/(main)/logs/[id]/page" is missing param "/logs/vCkOcmUZQdxA0muPBQTk" in "generateStaticParams()", which is required with "output: export" config.My requirement is that when I publish a log it should be saved to both local and firebase and when fetched it should be fetched only from localStorage on routes with
logs/id and from firebase on routes with logs/publish/idI looked at the documentation from nextJS and it seems to suggest to use
getStaticPaths: if you’re statically pre-rendering pages that use dynamic routes and:
The data comes from a database
But, It also reads
getStaticPaths will only run during build in production, it will not be called during runtime.
Some guidance on what is the best choice for my requirement would be really helpful.
Thanks
145 Replies
Airedale TerrierOP
The code sample of those two dynamic routes
and
pastelog/src/app/(publish)/logs/publish/[id] /page.tsx
This is the structure of the app
import Preview from '@/app/(main)/_components/Preview';
import type { Metadata } from "next";
import LogService from '../../_services/logService';
// This is required for dynamic routing in runtime
export const dynamicParams = true;
export const metadata: Metadata = {
title: "Pastelog",
description: "PasteLog is a simple, fast, and powerful pastebin. It is powered by firebase in the backend. It allows you to publish your logs, and access them from anywhere and any device via a unique link.",
};
export async function generateStaticParams() {
const logService = new LogService();
const logs = await logService.fetchLogs();
return logs.map(log => ({ id: log.id }));
}
export default function LogPage({ params }: { params: { id: string } }) {
const { id } = params;
return <Preview
logId={id}
/>;
};and
pastelog/src/app/(publish)/logs/publish/[id] /page.tsx
import Preview from '@/app/(main)/_components/Preview';
import LogService from '@/app/(main)/_services/logService';
// This is required for dynamic routing in runtime
export const dynamicParams = true;
export async function generateStaticParams() {
const logService = new LogService();
const logs = await logService.fetchLogs();
return logs.map(log => ({ id: log.id }));
}
export default function PublishPage({ params }: { params: { id: string } }) {
const { id } = params;
return <Preview
logId={id}
/>
};This is the structure of the app
Don't mix-up old nextjs with new, staticPath and StaticProps is used in Pages directory, and generateStaticParams is used in App router.
In your case read generateStaticParams doc's and focus on it
Logs/publish/[id]
-> pages.tsx
In here return array of id objects you expect from db, fetch all the IDs. And put it and return it in an array.
-> pages.tsx
In here return array of id objects you expect from db, fetch all the IDs. And put it and return it in an array.
Airedale TerrierOP
Thanks for the reply @muadpn
I found that the above error is because of this issue, I am getting
ReferenceError: localStorage is not defined
during dynamic segments routing hence the array is empty
I found that the above error is because of this issue, I am getting
ReferenceError: localStorage is not defined
during dynamic segments routing hence the array is empty
export async function generateStaticParams() {
const logService = new LogService();
const l = localStorage.getItem('logs');
console.log("fetchded during routing", l);
// returns an empty array
const logs = await logService.fetchLogsFromLocal();
console.log(logs);
return logs.map(log => ({ id: log.id }));
}Airedale TerrierOP
My app is pretty simple i have a
sidebar and a main content
sidebar is a client component which is fetching list of logs from local (works fine)
when I select a list item I am redirecting to logs/id which is this code logs/[id]/page.tsx
It is not necessary that I have to use the data from local Storage, I am okay with using fetching data from server provided I have the ID available in the main content (preview component)
sidebar and a main content
sidebar is a client component which is fetching list of logs from local (works fine)
when I select a list item I am redirecting to logs/id which is this code logs/[id]/page.tsx
It is not necessary that I have to use the data from local Storage, I am okay with using fetching data from server provided I have the ID available in the main content (preview component)
<Preview
logId={id}
/>;)Airedale TerrierOP
I am getting the errror only during navigation
This error is only during navigation and goes away on refreshing the browser
I have made a detailed post if anyone is interested to assist https://www.reddit.com/r/nextjs/comments/1di8ec9/error_page_is_missing_param_in/
This error is only during navigation and goes away on refreshing the browser
I have made a detailed post if anyone is interested to assist https://www.reddit.com/r/nextjs/comments/1di8ec9/error_page_is_missing_param_in/
@Airedale Terrier Thanks for the reply <@445154414068629504>
I found that the above error is because of this issue, I am getting
ReferenceError: localStorage is not defined
during dynamic segments routing hence the array is empty
export async function generateStaticParams() {
const logService = new LogService();
const l = localStorage.getItem('logs');
console.log("fetchded during routing", l);
// returns an empty array
const logs = await logService.fetchLogsFromLocal();
console.log(logs);
return logs.map(log => ({ id: log.id }));
}
Dude local storage is in browser, and not on server, generate static params works on server.
Airedale TerrierOP
Yes I understand that I am calling
please see the reddit link for the complete details
fetchLogs() (from server) in generateStaticParamsplease see the reddit link for the complete details
Well dude, you are trying to get firebase app on server which cannot be don, you need to initiate admin SDK for that
Those errors are shown because you are incorrectly sending params to the page. Either the data is invalid, and since firebase is client / browser the data won't be fetched at the server since there is no data it gives you error. This is to my point of view about firebase/next
Airedale TerrierOP
But fetchlogs in generateStaticParams is returning all the documents including the newly added document, attached is the structure of the document
Console log the data and check whether it's showing in terminal or the browser console.
Airedale TerrierOP
the console log of fetch logs is only in the terminal not in browser console
also when the error occurs refreshing the page the app works fine
Can you build it locally?
Airedale TerrierOP
Yes I am able to build and deploy using
npm run buildYou can check the issue at https://pastelog.web.app
Golden paper wasp
Please help: https://nextjs-forum.com/post/1252401550219939941
Can you share me the build log? How much pages are created, also can you delete .next and try to build again?
Airedale TerrierOP
sure, meanwhile the build runs, if you would like to see the actions log
https://github.com/maheshmnj/pastelog/actions/runs/9553678515/job/26333032686
https://github.com/maheshmnj/pastelog/actions/runs/9553678515/job/26333032686
Here is the complete attached logs
.next
Really weird, firebase client app supposed to run on client, not server. Anyway your issue is to implement static generation with local storage?.
Airedale TerrierOP
Yes
I am not sure what you mean by static generation?
My only requirement is to have published notes available at their own link just like a blogging post site has, the additional requirement is I am also storing those logs to local storage (client component) only to retrieve the ids in a sidebar
Can I get a summary of the current issue now
Airedale TerrierOP
Yes
I am seeing this error only during navigation
This is the folder structure of the app
Error: Page "/(publish)/logs/publish/[id]/page" is missing param "/logs/publish/BrWyKK8oGhiSAnTrLDAX" in "generateStaticParams()", which is required with "output: export" config.This is the folder structure of the app
root /
├──src
│ ├── app /
│ │ ├── (main)/
│ │ │ ├── _models/
│ │ │ │ ├── Log.ts
│ │ │ ├── _services/
│ │ │ │ ├── LogService.ts
│ │ │ ├── _components/
│ │ │ │ ├── Sidebar.tsx
│ │ │ │ ├── Navbar.tsx
│ │ │ │ ├── Pastelog.tsx
│ │ │ │ │
│ │ │ ├── logs /
│ │ │ │ ├──[id]
│ │ │ │ │ └── page.tsx
│ │ │ │ └── layout.tsx
│ │ │ │ └── page.tsx
│ │ ├── (publish)/
│ │ │ ├── logs /
│ │ │ │ ├── publish /
│ │ │ │ │ ├──[id]/
│ │ │ │ │ └── page.tsx
│ │ │ └── layout.tsx
│ │ │
│ │ └── layout.tsx
│ │ └── global.css
│ │ └── page.tsxadding more
ya, you need to export a function
getStaticParamsAiredale TerrierOP
I have a sidebar and a MainContent (Pastelog/Preview)
renders
Pastelog: at
Preview: at
- Sidebar is a client component which renders list of logs from local storage (works fine)
- Pastelog has a button to publish the logs and redirect to
When I hit publish I am saving the data to firestore and local storage and redirecting to dynamic route
(method to publish)
The data is getting stored in both local storage and firestore but when I redirect to dynamic route I am seeing this error
renders
Pastelog: at
baseurl/logsPreview: at
baseurl/logs/[id]- Sidebar is a client component which renders list of logs from local storage (works fine)
- Pastelog has a button to publish the logs and redirect to
baseurl/logs/publish/idWhen I hit publish I am saving the data to firestore and local storage and redirecting to dynamic route
(method to publish)
async function publish() {
setLoading(true);
const log = new Log(
expiryDate.toDate('UTC'),
content,
new Date(),
LogType.TEXT,
true,
title,
false,
);
const id = await logService.publishLog(log);
if (!id) {
setLoading(false);
return;
}
router.push(`/logs/publish/${id}`);
setLoading(false);
}The data is getting stored in both local storage and firestore but when I redirect to dynamic route I am seeing this error
Error: Page "/(publish)/logs/publish/[id]/page" is missing param "/logs/publish/BrWyKK8oGhiSAnTrLDAX" in "generateStaticParams()// logs/publish/[id]/page.tsx
import Preview from '@/app/(main)/_components/Preview';
import LogService from '@/app/(main)/_services/logService';
// This is required for dynamic routing in runtime
export const dynamicParams = true;
export async function generateStaticParams() {
const logService = new LogService();
const logs = await logService.fetchLogs();
// logs.forEach(log => console.log(log.id));
return logs.map(log => ({ id: log.id }));
}
export default function PublishPage({ params }: { params: { id: string } }) {
const { id } = params;
return <Preview
logId={id}
/>
};This is the nextjs config
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true
}
};
export default nextConfig;This error is only during navigation and goes away on refreshing the browser
Can you provide a min repro repo?
Airedale TerrierOP
here is the repository (not minimal) https://github.com/maheshmnj/pastelog/tree/web/
but I think the code is fairly simple incase you need me to reduce the code further I can do that and get back
but I think the code is fairly simple incase you need me to reduce the code further I can do that and get back
I'll look int this issue tonight when I get free
Airedale TerrierOP
reproduction guidelines here http://pastelog.web.app/logs/publish/A2IPVQ02ETXtsQ2qretK/
link will be active in next 5 mins
link will be active in next 5 mins
@Airedale Terrier reproduction guidelines here http://pastelog.web.app/logs/publish/A2IPVQ02ETXtsQ2qretK/
link will be active in next 5 mins
Airedale TerrierOP
This link is active now this link is of the same app where the issue is, Strangely this link works only in incognito
You basically won't be even able to view logs.
Or if you're writing to database from client side, you can set the path page.tsx to a client file
Airedale TerrierOP
@Anay-208 thanks for taking a look, page.tsx has
generateStaticParams so we cannot use "use client"I have created a minimal reproduction if you would like to take a look https://github.com/maheshmnj/pastelog/tree/routing/src/app
@Airedale Terrier <@755810867878297610> thanks for taking a look, page.tsx has `generateStaticParams` so we cannot use "use client"
Can you directly send me the github link of the file?
In dev version, what happens if you visit
/logs/publish/BrWyKK8oGhiSAnTrLDAXAiredale TerrierOP
it works the first time takes almost 7-10 secs to redirect, and when I go back (browser back button) publish again I see the error
@Airedale Terrier it works the first time takes almost 7-10 secs to redirect, and when I go back (browser back button) publish again I see the error
Can you share a screen recording of behaviour? I didn’t really get what you mean?
Airedale TerrierOP
sure
here you go
@Airedale Terrier here you go
Now stop the dev server. Then visit any log, then try publishing
If I’m right, it will fail
Airedale TerrierOP
This is in production (deployed app)
I'm currently talking about development only
I think I found the cause to the problem, but I need to verify
@Airedale Terrier here you go
First of all, Visit any log
Then try publishin
@Anay-208 Now stop the dev server. Then visit any log, then try publishing
Airedale TerrierOP
Stop the dev server and start again and visit any log?
yes
Then try publishing
Airedale TerrierOP
visit at logs/id?
or logs/publish/id
logs on the sidebar redirect at logs/id
Airedale TerrierOP
So it failed
Airedale TerrierOP
yes
So how its working is that, with
out paramAnswer
So Whenever you visit the page, It first of all, gets all the log ids from the database
and it saves the content of the log
And if you try to visit the page again, It'll display whatever content it has
But It didn't find any content for that param
and thats resulting in an error
You can't use static build with this
Airedale TerrierOP
so what is other alternative apart from static build?
The normal build
Which you can deploy to vercel, cloudflare pages
Also, Mark my answer as a solution here in stackoverflow: https://stackoverflow.com/questions/78634909/error-page-is-missing-param-generatestaticparams-which-is-required-with-o/78642841#78642841
@Anay-208 You can't use static build with this
And mark this message here
Airedale TerrierOP
what do you mean by out param ?
@Airedale Terrier what do you mean by out param ?
in next.config.js|ts, you've added
Airedale TerrierOP
you mean output:export?
when I remove that and do a normal build
npm run build I don't see the out folder generatingyes
@Airedale Terrier you mean output:export?
You've added this, which results in a static build
You can remove that, and the issue will be fixed, and also remove generateStaticParams
And it should fix the issue
but you won't be able to use static build
Airedale TerrierOP
after removing output:export the dynamic page won't receive params right?
PublishPage({ params }import Preview from '@/app/(main)/_components/Preview';
import LogService from '@/app/(main)/_services/logService';
// This is required for dynamic routing in runtime
export const dynamicParams = true;
// export async function generateStaticParams() {
// const logService = new LogService();
// const logs = await logService.fetchLogs();
// return logs.map(log => ({ id: log.id }));
// }
export default function PublishPage({ params }: { params: { id: string } }) {
const { id } = params;
return <Preview
logId={id}
/>
};Airedale TerrierOP
Awesome this is working fine locally can't thank you enough
@Anay-208 You can't use static build with this
Can you mark this message as a solution?
Airedale TerrierOP
I would have loved to offer you a bounty on the stackoverflow, I was about to start a bounty
@Airedale Terrier I would have loved to offer you a bounty on the stackoverflow, I was about to start a bounty
should I delete the answer, so you can start bounty?
Airedale TerrierOP
You can do that yes
stackoverflow doesn't allow starting a bounty atleast two days after posting the question
Please add a detailed answer after I start a bounty
@Anay-208 You can't use static build with this
Alright, Can you mark this message as solution here?
By right clicking>Apps>Mark solution
Airedale TerrierOP
regarding generating a normal build
where are the output files generated to deploy?
@Airedale Terrier where are the output files generated to deploy?
Inside .next folder IIRC
And you’ll have to deploy it to Vercel, cf pages, or self host it
Airedale TerrierOP
I see looks like firebase hosting doesn't support it https://github.com/maheshmnj/pastelog/actions/runs/9583200980/job/26423933685#step:5:82
However, I recommend google cloud run
If talking about services within google
I personally use cloudflare pages to deploy nextjs apps
Airedale TerrierOP
I would like to keep this free domain from firebase pastelog.web.app
I am not looking to pay for the services for this app at this time.
I am not looking to pay for the services for this app at this time.
With google cloud run, you can also add domain to firebase
@Airedale Terrier I would like to keep this free domain from firebase pastelog.web.app
I am not looking to pay for the services for this app at this time.
Google cloud run has a really generous free tier
You can directly add a firebase domain to google cloud run
Airedale TerrierOP
Will take a look at that trying this for now
npm run build && npm run export && firebase deploy --only hostinglooks like export is for static sites in old version of nextjs
You've to use either app hosting or cloud run
Airedale TerrierOP
I deployed it to vercel and its working perfectly fine. https://pastelog.vercel.app/
I will notify you here once I start the bounty
I will notify you here once I start the bounty
Airedale TerrierOP
Does anyone know how to access env variables in cloud run? I added them to cloud run but looks like they are not accessible
Airedale TerrierOP
vercel takes care of it, this is the app in cloud run https://pastelog-d6s7zhnvha-uc.a.run.app/logs/
I found this solution which suggest using a dockerfile but looks like we will have to push the dockerfile to github that way the variables will be exposed
https://stackoverflow.com/a/67327550/8253662
https://stackoverflow.com/a/67327550/8253662
Airedale TerrierOP
Is it possible to point the firebase domain to cloud run deployed app?
Click manage custom domain
and you can deploy with firebase
Airedale TerrierOP
tried this
not sure what is subdomain siteid
I used the one I found by running
firebase hosting:sites:listlooks like it worked this time
Airedale TerrierOP
I realized that this error is because site with id 'pastelog' already exists I tried creating a new site with id
pastelog-prod it worked need to figure out how to change the id@Airedale Terrier can you start a bounty then?
Airedale TerrierOP
I started the bounty, Please add a clear answer and up vote the question too thanks
Posted @Airedale Terrier, I basically edited & undeleted prev one
let me know when done
Airedale TerrierOP
Thanks I will be able to award the bounty after 24 hours