Dynamic Routes

Implement getStaticProps

We need to fetch necessary data to render the post with the given id.

To do so, open lib/posts.js again and add the following getPostData function at the bottom. It will return the post data based on id:

export function getPostData(id) {
  const fullPath = path.join(postsDirectory, `${id}.md`)
  const fileContents = fs.readFileSync(fullPath, 'utf8')

  // Use gray-matter to parse the post metadata section
  const matterResult = matter(fileContents)

  // Combine the data with the id
  return {
    id,
    ...matterResult.data
  }
}

Then, open pages/posts/[id].js and replace this line:

import { getAllPostIds } from '../../lib/posts'

with the following code:

import { getAllPostIds, getPostData } from '../../lib/posts'

export async function getStaticProps({ params }) {
  const postData = getPostData(params.id)
  return {
    props: {
      postData
    }
  }
}

The post page is now using the getPostData function in getStaticProps to get the post data and return it as props.

Now, let's update the Post component to use postData. In pages/posts/[id].js replace the exported Post component with the following code:

export default function Post({ postData }) {
  return (
    <Layout>
      {postData.title}
      <br />
      {postData.id}
      <br />
      {postData.date}
    </Layout>
  )
}

That’s it! Try visiting these pages:

You should be able to see the blog data for each page:

Great! We’ve successfully generated dynamic routes.

Something Wrong?

If you come across an error, make sure your files have the correct code:

If you’re still stuck, feel free to ask the community on GitHub Discussions. It’d be helpful if you could push your code to GitHub and link to it so others can take a look.

Summary

Again, here’s the graphical summary of what we’ve done:

We still haven’t displayed the blog markdown content. Let’s do this next.

Quick Review: How does params.id from getStaticProps({ params }) know the key is named id?