In the getStaticPaths function, there is a path returned with params postId:1. If have two or three more params with postId: 2, postId: 3 etc. those will be statically generated. Right?
Is there a way not to statically load any post with any id? If I want to load all the posts with the loading screen, is that can be made possible?
import {useRouter} from "next/router" export default function Post({ post }) { const router = useRouter() if (router.isFallback) { return <h1>Loading...</h1> } return ( <> <h4>{post.id} - {post.title}</h4> <p>{post.body}</p> </> ); } export async function getStaticPaths() { return { paths: [ { params: { postId: "1" } } ], fallback: true, }; } export async function getStaticProps(context) { const { params } = context; const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${params.postId}` ); const data = await response.json(); if(!data.id) { return { notFound: true } } return { props: { post: data, }, }; }
Advertisement
Answer
I think you’re looking for a solution to fetch dynamic data for a static page instead of serving a fallback page from static-side generation.
I’d propose 2 options:
You can use server-side rendering with getServerSideProps
. Of course, all HTML will be generated during run-time (HTML generation per request)
export async function getServerSideProps(context) { const { params } = context; const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${params.postId}` ); const data = await response.json(); if(!data.id) { return { notFound: true } } return { props: { post: data, }, }; }
The second option is Incremental static regeneration (ISR) (available from version 9.5). This is the upgrade version of static-site generation (SSG) and likely a hybrid between SSG and SSR, it will generate all static HTML with defined paths in getStaticPath
(like SSG), BUT if the path, which a user has fetched, is not defined, it will automatically generate HTML on the fly, and then cache it on the server (like other generated HTMLs in SSG). To have this behavior, you need to use fallback: 'blocking'
in getStaticPaths
(If you want to understand how fallback
works, you can check this document out)
ISR is also providing a revalidation mechanism. You can set the timer for updating your generated HTML due to API’s data update. The only downside of this feature is that is only available from Next.js 12.1, so you can consider upgrading your Next.js version for this implementation.
export async function getStaticPaths() { return { paths: [ { params: { postId: "1" } } ], fallback: "blocking", //Next.js 9.5 - generate a new HTML based on user demand if the path is not defined }; } export async function getStaticProps(context) { const { params } = context; const response = await fetch( `https://jsonplaceholder.typicode.com/posts/${params.postId}` ); const data = await response.json(); if(!data.id) { return { notFound: true } } return { props: { post: data, }, revalidate: 10, //Next.js 12.1 - Validate data to regenerate static HTMLs every 10 seconds }; }