Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get param from url in getStaticProps without using getStaticPaths?

Here is my function below in which I am using the getServerSideProps() method and fetch data dynamically according to the param post_slug from my URL.

// This gets called on every request
export async function getServerSideProps({ query }) {
  const { post_slug } = query || {};

  let url = API_URLS.POST.GET_POST_BY_SLUG;

  url = url.replace(/#POST_SLUG#/g, post_slug);

  const res = await fetch(url);
  const { data } = (await res.json()) || {};

  // Pass post_data to the page via props
  return { props: { data } };
}

But this function render a whole page on every request.

So now I decide to use getStaticProps() but here I could not get param post_slug from URL.

I read next js documentation where they tell I need to use getStaticPaths() along getStaticProps() method but here the problem is I have to define static params in getStaticPaths() method but I want param from my current URL.

Is there any solution to get param post_slug from URL in the getStaticProps() method?

like image 456
Sourav Singh Avatar asked Dec 31 '22 22:12

Sourav Singh


2 Answers

You can do so using getStaticPaths with fallback set to true to get params(not query) and create the static page at request time.

In that case, when visitors visit paths that have not been generated at build time, Next.js will serve a "fallback" version of the page on the first request to such a path (It can simply be <div>Loading...</div>)

Next.js will then run getStaticProps and build the page and data json for the first time and serve to the visitor when ready.

Next.js also adds this path to the list of pre-rendered pages so subsequent requests to the same path will serve the generated page, just like other pages pre-rendered at build time.

In your case, you can't simply swap out getServerSideProps with getStaticPaths. You will have to create a [postSlug].js to use the param postSlug.

// Example code
import { useRouter } from 'next/router';

function Post({ post }) {
  const router = useRouter();
  if (router.isFallback)  return <div>Loading...</div>;
  // Render post...
}

export async function getStaticPaths() {
  return {
    paths: [{ params: { postSlug: 'sth' } }, { params: { postSlug: 'sth-else' } }],
    fallback: true,
  };
}

export async function getStaticProps({ params }) {
  const res = await fetch(`https://.../posts/${params.postSlug}`);
  const post = await res.json();
  return {
    props: { post },
  }
}

export default Post;

To update the statically generated pages, check out Next.js Incremental Static Regeneration

like image 82
hangindev.com Avatar answered Apr 25 '23 10:04

hangindev.com


export async function getStaticPaths() {
  return {
    paths: [],
    // Enable statically generating additional pages
    // For example: `/posts/3`
    fallback: true,
  }
}

This piece of information is already mentioned in docs, link.

Quoting the docs:

fallback: true is useful if your app has a very large number of static pages that depend on data (think: a very large e-commerce site). You want to pre-render all product pages, but then your builds would take forever.

Instead, you may statically generate a small subset of pages and use fallback: true for the rest. When someone requests a page that’s not generated yet, the user will see the page with a loading indicator. Shortly after, getStaticProps finishes and the page will be rendered with the requested data. From now on, everyone who requests the same page will get the statically pre-rendered page.

This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.

If you don't want to show Loader state but instead want to show Browser requesting page(first time only, will be added in pre-generated pages for consecutive req.) fallback:"blocking"

For Development, getStaticPaths and getStaticProps will be called on every request.

like image 26
Alia Anis Avatar answered Apr 25 '23 09:04

Alia Anis