This question already has an answer here:
Fetch error when building Next.js static website in production
(1 answer)
Closed 11 months ago.
I am using Next.js with the Vercel deployment workflow, I am following this guide to try and setup page generation at buildtime. The specific section shows the following example to generate pages based on an external API's response:
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map(post => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
I want to do this exactly, however I wrote my API as a Node.js serverless function within the same code repository, it is not an external api.
I tried to do the following to call on my api:
// This function gets called at build time
export async function getStaticPaths() {
const res = await fetch('/api/get-designs');
const designs = await res.json();
// Get the paths we want to pre-render based on posts
const paths = designs.map(design => ({
params: { id: design.id },
}))
return {
// Only posts returned by api are generated at build time
paths: paths,
// Enable statically generating additional pages
fallback: true,
}
}
However I get an error that the fetch api url must be absolute. Because of the way Vercel deploys, I won't always have the same deployment URL, so I don't think I can just use a hardcoded value here. Also, I am suspecting that because this function runs at buildtime, that my function is not running yet, therefore can not be called. I am still trying to wrap my head around this Next.js statically generated site workflow, but basically I am confused because they seem to encourage using serverless functions, and this getStaticPaths method for page generation, but they don't seem to work together unless I am missing something.
Is there a way I can run my api to get these results at build time? Any guidance would be much appreciated!
Thanks!
In this case, we can extract the server logic into a function and that function can be used directly inside your api route file. So, for CR we can use /api/whateverRoute and inside getStaticPaths we can use that function itself directly.
Related
I am trying to send a function as one of the value from a remix route loader function
export const loader: LoaderFunction = async ({ request }) => {
const userId = await requireUserId(request)
const user = await getUserById(userId)
const canUserPerformAction = getUserPermissions(user)
const organisations = await Organisation.find({}).exec()
return {
organisations,
canUserPerformAction
}
}
getUserPermissions(user) returns a function with the current user context, which needs to be used in the frontend.
this function always ends up being undefined when I fetch it using useLoaderData() in the default component/ frontend. Is there a better way to do this?
Your loader can either be called during the whole page generation, or using an XHR when navigating in your app.
Your loader have to return a valid Response object, which will usually be a JSON response : https://remix.run/docs/en/v1/api/conventions#returning-response-instances
In your code sample, the returned object is automatically converted to a JSON string, and since functions aren't valid json, it gets stripped.
You will need to call your canUserPerformAction and return its actual result as JSON.
Greetings to everyone,
I have just started to learn NodeJS and have been experimenting on API routes in NextJS as its easy to setup and see what's actually going on, So I know how to make a basic get request but I'm interested in something a little complex.
So I'm trying to build an API route that can be filleted by page number, so for example api/pages/1 would return page 1 and so on.
so this is my file in /api/game.js
export default async function handler(req,res) {
const response = await fetch('https://exampleapi.com/pages/?sort=&page=1&per_page=50')
const jsonData = await response.json();
res.status(200).json(jsonData);
}
Now this works obviously but I want to know how I can make dynamic routes for all the pages. Since I'm using an external API I'm not sure how many pages exist at any moment.
So far I have created another folder and called the file [gamepage].js, I'm not sure how I would manipulate the fetch call in the game.js file in here.
export default async function handler(req, res) {
const { pno } = req.query
console.log(pro)
const response = await fetch(`https://exampleapi.com/pages/?sort=&page=${pno}&per_page=50`)
const jsonData = await response.json();
res.status(200).json(jsonData);
}
Sorry if the question is too beginner level, I'm just getting started with backend JS.
I got it to work, I was just missing the gamepage from req.query
const { pno } = req.query.gamepage
this did it.
This question already has an answer here:
Next js nested dynamic routes: data fetching via getstaticprops with shared data between routes
(1 answer)
Closed last year.
im fetching a huge json data from an external API inside my getstaticprops. this data will then be divided into parts to be send to other static pages (hundreds of pages) as props.
// page1.tsx
const page1 = ({ page1Data }) => {
...
}
const getStaticProps: GetStaticProps = async () => {
const res = await fetch('https://hugedata')
const jsonData = await res.json()
const { page1Data, page2Data, page300Data, ...allData } = jsonData
return { props: { page1Data } }
}
i only know how to send the staticprops data to the component inside the file like this.
is there a way send these data to other static pages/routes ? (e.g. to page2.tsx)
It's not really possible to send data between pages. But you can see the methods described here.
I suggest you really check router and inspect data inside it, you can find a lot of info about data on the page.
P.S. As I see, you are trying to get a lot of data and you need to use pagination and split it to the parts, you can use this lib
I made this restaurant's website and uses Google Spreadsheet to feed content into the menu pages. The choice of such method was based on simplicity and client expertise.
I'm using google-spreadsheet package to fetch all the information I need from this document on Google Drive...
//** ../pages/api/cardapios/index.js
import { GoogleSpreadsheet } from "google-spreadsheet";
export default async function getCardapioFromSlug(indexNumber) {
try {
const doc = new GoogleSpreadsheet(<%GOOGLE_SPREADSHEET_ID%>)
await doc.useServiceAccountAuth({
client_email: process.env.GOOGLE_SHEETS_SERVICE_ACCOUNT_EMAIL,
private_key: process.env.GOOGLE_SHEETS_PRIVATE_KEY,
});
await doc.loadInfo()
const cardapio = doc.sheetsByIndex[indexNumber]
const rows = await cardapio.getRows()
if (rows.length) {
return rows.map(({
Código,
Produto,
Unidade,
Descrição,
Valor,
Procedência,
Categoria
}) => {
return {
Código,
Produto,
Unidade,
Descrição,
Valor,
Procedência,
Categoria
}
})
}
} catch (err) {
console.log(err)
}
return [];
}
...then feeding it into the page using getStaticProps() function. It worked like a charm once I've got all things setup properly.
// ../pages/unidades/[slug].js
export async function getStaticProps({ params }) {
const sanityData = await getCardapio(params.slug)
const indexNumber = sanityData[0].id
// console.log("index number", indexNumber)
const produtos = await getCardapioFromSlug(indexNumber)
const produtosStringfied = JSON.stringify(produtos)
const produtosArray = JSON.parse(produtosStringfied)
return {
props: {
cardapio: {
info: sanityData[0] || null,
items: produtosArray || null
}
},
revalidate: 1
}
}
The problem is after we changed values for some cells in the source document, the content wasn't automatically updated in the site.
I've tried redeploying (with both build cache on and off) it so the build process would grab the content from the document one more time and update the site, but it didn't worked. One idea was to make a webhook that would be avaiable for the client to run a simple command on his machine and rebuild the page with the new info, but this approach seems to be useless.
I red some articles (this one for instance) on custom webhooks for Google Spreadsheets but I can't really understand how it would trigger something on my page. Don't really think it would actually work.
Now I'm kind of stuck on where should I go. Perhaps I should rewrite my getStaticProps()?
The issue has nothing to due with the code itself, but the misuse of the API. The id from the spreadsheet was wrong, still using a prototype which was used as base to the final one the client has. Changed the env var and everything went fine.
Had to force deploy ignoring build cache via vercel cli. Thanks to anyone that spent time commenting and wondering about this issue.
We are currently working on a Nextjs project which includes a number of dynamic pages. We have come to a stage where we are defining the dynamic paths using getStaticProps and getStaticPaths. So far we managed to define 404 pages in dynamic pages with a similar structure to the below:
export async function getStaticProps(context) {
const { id } = context.params
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
const user = await response.json()
return {
props: { user },
notFound: Object.keys(user).length === 0
}
}
export function getStaticPaths() {
return {
paths: [],
fallback: 'blocking'
}
}
Using version 10's notFound value and fallback: blocking allows us to have the page return a 404 status code (for some reason fallback: true returns a 200 status code).
The issue we currently have is to display a 404 page to pages that depend on user data such as username or user locale. One way we thought we could solve this is by having those pages as Server Side generated rather than Static Site generated by using getServerSideProps:
export async function getServerSideProps(context) {
const userId = getCookie('user_id')
const response = await fetch(`___/checkUserAccess/${userId}`)
const access = await response.json()
return {
props: { ... },
notFound: !access.userAllowed
}
}
I suppose I am answering my own question here as going for Server Side for these pages to show 404 pages based on user data seems logical. However the concern is the impact it may have on the website as a whole. These pages could easily end up being hundreds of pages.
Should we be concerned about this? Or maybe there's another way to go about solving this?