Table of Contents

Next - Static Page Generation with a dynamic route that catch-all routes

About

An example on how to catch all routes with two parameters.

The below codes belong to one file /pages/exam/[...slug].tsx that will respond to url such as:

where:

Example Steps

Define the slug with getStaticPaths

The getStaticPaths defines all possible paths and define the slug part as an array.

import { GetStaticPaths } from 'next';
/**
 * The paths returned as argument will be build at build time.
 */
export const getStaticPaths: GetStaticPaths = async () => {
  
  // Define all paths to be pre-render 
  // The slug is an array 
  // The slug name is slug because this is the name of the file `...slug.js`
  const paths = questions
    .map(question => ({
      params: { slug: [question.examId,question.questionId]  },
    }))

  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

Parse the slug, fetch more data and build props with getStaticProps

import { GetStaticProps } from 'next';
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export const getStaticProps: GetStaticProps = async ({ params }) => {
  try {
    const slug: string[] = (params?.slug as string[])
    const examenId: number = Number(slug[1]);
    const questionId: number = Number(slug[3]);
    // The props attribute is the argument of the StaticPropsDetail component (ie 
    return {
      props: {
        examen: examenId,
        question: questionId
      }
    }
  } catch (err) {
    return { props: { errors: err.message } }
  }
}

A static component that consume the previous build props

type QuestionProps = {
  examId: number,
  questionId: number,
  errors: string
}

export default function QuestionPage(props: QuestionProps) {

  const { examId, questionId, errors } = props;
  
  if (errors) {
    return (
      <Page title={`Error`}>
        <p>
          <span style={{ color: 'red' }}>Error:</span> {errors}
        </p>
      </Page>
    )
  }
  return (
     <div>
      <h1>Question {questionId} from Exam {examId}</h1>
     </div> 
    
  )
}