Next.js makes it easy to create dynamic routes for web applications, allowing you to build a route for every item in a database. This is achieved through the use of parameters in the route path.
For example, if you're building a blog, you can create a route for every blog post by using the post's ID as a parameter. This enables users to access specific blog posts by visiting the corresponding URL.
Dynamic routes can be defined using the getStaticPaths method, which is used to pre-render pages at build time. This method returns an object with a paths property, which is an array of route paths.
By using dynamic routes, you can create a scalable and efficient web application that can handle a large number of pages.
Related reading: Next Js Using State Context
Routing Basics
The Next.js project comes with a pages folder, which determines the structure of your routes. Every file inside that folder maps to a route in your application.
Additional reading: What Is .next Folder in Next Js
To create a static route, you can add a new file in the pages folder, such as index.js or a named file like about.js. pages/index.js maps to the root URL (/).
Dynamic routes, on the other hand, require brackets around parameters (e.g [id]) as a filename. For example, to create a blog with a route such as myblog.com/posts/:id, you would create a [id].js file inside the posts folder.
The Link component in Next.js allows for navigation between pages. It can accept an href and wrap around a piece of code to navigate to a page.
Here are the different types of routing in Next.js:
- Static routing: defined by a page that returns the same component, regardless of the time the user clicks on it.
- Dynamic routing: user is shown different data based upon the parameters provided in the route.
Next.js utilizes a file-system for the concept of routing, which is different from the code-based approach used in React.
Here's a summary of the different types of routes:
Dynamic routing can be implemented in multiple ways, but one simple way is to use bracket syntax (e.g [id].js) to denote a dynamic segment. The useRouter hook has a query object property that exposes dynamic route parameters.
For example, routing to /post/123 will give the query object {"id": "123"}.
See what others are reading: Query in Nextjs
Creating Routes
In Next.js, every project comes with a pages folder that determines the structure of your routes. The pages folder itself represents your root URL (/).
To create a new route, you need to add a file in the pages folder. For static routing, you can create a new route by adding an index.js or a named file like about.js. pages/index.js maps to /.
But how does it work for dynamic routes? Say you wanted to create a blog, how would you add a route such as myblog.com/posts/:id? Next.js handles dynamic routes by supporting brackets around parameters (e.g [id]) as a filename.
To create a dynamic route, you would create a [id].js file inside your posts folder. /pages/posts/[id].js would map to /posts/[id] where id is the unique id of your post.
Here's a breakdown of the syntax:
- For static routes, use a file like index.js or about.js
- For dynamic routes, use a file like [id].js
- For nested routes, create a folder instead of a file, like [id]
For example, if you want to create a route like /posts/[id]/[commentId], you would create a folder called [id] inside your posts folder, and then add a new file inside that folder, like [commentId].js.
Curious to learn more? Check out: Nextjs Cookies
Route Navigation
Route Navigation is a crucial aspect of Next.js dynamic routing. You can navigate to dynamic routes using the Link component, which accepts an object with pathname and query parameters.
The Link component takes those two and automatically formats it into the right url. This is much better than hard-coded urls, which can become outdated if the route changes.
You can also access the router and navigate to a new page using the useRouter hook. This hook allows you to push a new page or go back in the navigation stack.
To access query parameters in your page, you can import the useRouter hook and get the router object. This will give you access to the query parameters, such as the id in the /posts/[id] route.
Here's a table summarizing the different ways to navigate to dynamic routes:
Accessing Route Data
You can access the parameters in your new page by using the router object. Simply import useRouter and get the router object.
The router object provides access to the current route and its parameters. You can use it to retrieve the query parameters passed to the page.
For example, if you have a page with a dynamic route like /posts/[id], you can access the id parameter using the router object.
You can also use the useRouter hook to navigate to a new page, not just through a link. This can be useful when you want to navigate to a new page based on user input or other events.
To access the query parameters, you can use the query object returned by the useRouter hook.
Here's an example of how to access the query parameters:
- Import the useRouter hook: `import { useRouter } from 'next/router';`
- Get the router object: `const router = useRouter();`
- Access the query parameters: `const { id } = router.query;`
With this approach, you can easily access the parameters passed to your page and use them to render the correct data.
Dynamic Routing
Dynamic routing is a powerful feature in Next.js that allows you to create routes that can handle different parameters. You can create dynamic routes by using square brackets in your page file names, such as [id].js.
A different take: Create Next Js App
This approach is particularly useful for creating routes that can handle multiple pages with different parameters, such as a blog where each post has a unique ID. You can also use dynamic routing to create nested routes, where each route has its own set of parameters.
To navigate between dynamic routes, you can use the Link component, which accepts an object with pathname and query parameters. This allows you to create links that can handle dynamic routes without having to hard-code the URL.
Here are some examples of how to use dynamic routing in Next.js:
Remember to use the useRouter hook to access the query parameters in your page, and don't forget to use getStaticPaths() to pre-render dynamic routes at build time.
Recommended read: 'use Server' Nextjs
Nested Route
You can create nested routes in Next.js by creating a folder instead of a file. This is done by using the same syntax as dynamic routes, with square brackets around the parameter.
Dynamic nested routes can become complex and redundant if you need to create a route for every page you need to render. For example, if you have 1,000 posts on your blog, it would be ridiculous to need to create 1,000 routes, one for each post.
To solve this, you can use dynamic routes! Let's take a look at an example:
pages/post/[author]/[id].js:
pages/rest/[detail].js
This structure allows you to create multiple routes for different authors and posts, without having to create a separate route for each one.
Here's a breakdown of the syntax:
- `pages/post/[author]/[id].js` maps to `/post/[author]/[id]`
- `pages/rest/[detail].js` maps to `/rest/[detail]`
By using this structure, you can create a scalable and maintainable routing system for your Next.js application.
Imports and Interface
To create a dynamic route in Next.js, you'll need to import the necessary modules. If you're using TypeScript, you'll need to import the interface starInterface.
When working with dynamic routes, it's essential to understand how the user's URL affects the code. Let's say the user reaches out to /test/St2-18, then itemID would hold the value of St2-18.
You can use JavaScript instead of TypeScript, but keep in mind that you'll need to import GetStaticProps and GetStaticPaths from 'next' separately.
See what others are reading: Nextjs Dynamic Routing
Pre-rendering and Fallback
Pre-rendering in Next.js is a crucial concept to grasp for dynamic routing. It generates HTML for each page in advance and hydrates them when loaded, with two forms: static generation (SG) and server-side rendering (SSR).
Static generation is recommended for applications that don't deal with frequently changing data, as it offers better performance. To use static generation, you should pre-render with the function getStaticProps, which generates HTML at build time. A blog post is a good example of a page that should be generated statically.
For applications that need to fetch data at request time, server-side rendering is a better choice. You can use the getServerSideProps function to make data requests at the server level. This will be covered later in the article.
The fallback property is particularly useful in handling cases where a user tries to access a path that doesn't exist in getStaticPaths(). There are three options for the fallback property: false, true, and 'blocking'.
Discover more: Next Js Client Side Rendering
Here's a summary of the fallback property options:
- fallback set to false leads to a 404 error page.
- fallback set to true doesn't automatically lead to a 404 error page, allowing the frontend to handle the situation.
- fallback set to 'blocking' doesn't automatically lead to a 404 error page, omitting manual loading processes.
Pre-rendering
Pre-rendering is a crucial concept in Next.js that enables you to generate HTML for each page of your application in advance.
Next.js offers two forms of pre-rendering: static generation (SG) and server-side rendering (SSR). Static generation generates HTML at build time, while server-side rendering generates HTML at request time.
For applications that don't deal with frequently changing data, static generation is highly recommended for better performance. You can use the getStaticProps function to pre-render with static generation when you don't need to get external data at request time.
A blog post is an example of a page that should be generated statically, but if you need to get data at request time, use the getServerSideProps function. This function gets called by the server on every request.
Static generation is ideal for pages like blog posts where the data doesn't change often. However, if you need to get data at request time, server-side rendering is a better choice.
Intriguing read: Nextjs Loading Component
Testing the Fallback Property
Testing the Fallback Property is crucial to understand how it affects your application's behavior. The fallback property can be set to true, false, or 'blocking' to see how it changes the application's behavior.
Using fallback: true allows you to insert one possible path without causing the application to crash. This is demonstrated when paths is set to ['/test/St2-18'].
With fallback: true, you can still access other paths, but you'll notice a brief Loading... message appears before the data is loaded. This is because of the if-statement with router.isFallback.
Using fallback: 'blocking' and paths: ['/test/St2-18'] will make the browser take a moment longer to load the data, but you won't see any Loading... message. This is in contrast to fallback: true, where the Loading... message appears briefly.
If this caught your attention, see: Nextjs App Router Tailwind Loading Page
Project Setup and Configuration
To set up a Next.js project for dynamic routing, create a subfolder called test in the pages folder. This folder gets automatically created by Next.js.
For dynamic routing, you'll need a file like [something].tsx (or .js if you're using JavaScript) in the test folder. This file will contain the dynamic route's content.
In your project, you'll also need a backendData folder at the root level with a file called some-backend-data.json. This file provides the data that will be inserted dynamically into your page.
A unique perspective: Next Js Fetch Data save in Context and Next Route
Configuring the Frontend
To configure the frontend, you'll need to set up your page content.
The fallback from getStaticPaths() can be set to true or 'blocking' if you're unable to provide every dynamic route for pre-loading.
This will prevent your page from crashing, and instead load on the fly as the user accesses the specific dynamic route.
You can use router.isFallback to return JSX with a loading indication for the user.
If the user reaches a dynamic path with data that can be fetched, the intended JSX output will be returned.
For example, if you configure the frontend with fallback: true, you'll receive the actual intended JSX output for a valid path like /test/St2-18.
However, if you try to put in an invalid parameter, it will first try to load and then return your manual set up error message, as seen with the /test/this-will-produce-an-error path.
For your interest: Nextjs Error Boundary
Project Setup
To set up your Next.js project, start by creating a subfolder in the pages folder, which gets automatically created by Next.js. This subfolder will hold a file like [something].tsx, which is a TypeScript file.
For the data, create a backendData folder at the root level of your Next.js application. This is where you'll store files like some-backend-data.json.
The pages folder is automatically created by Next.js. This is where you'll find your [something].tsx file, which is a TypeScript file.
See what others are reading: Nextjs File Structure
Setup for GetStaticProps
In a Next.js project, you'll need to create the getStaticProps() function to enable pre-rendering for specific fetched data in dynamic routes.
For JavaScript, you can omit GetStaticProps as the type for getStaticProps(). This function provides a context parameter that allows you to access params and reach the current identifier of your specific path.
The context object is accessed through the file name, which is why you'll see something in the context. This is because the file is actually called something.tsx.
Additional reading: Nextjs Server Actions File Upload
You'll use your handy getData() function to get your backend data and save it to data. This function will come in handy later when you try to fetch dummy backend data.
You can combine the itemID and data variables to create foundItem, which returns the object that includes the itemID as an id.
If no data can be found, you return a boolean hasError with the value true to help manage such cases on the frontend. This is done with an if statement that checks if foundItem actually exists.
If there is data, you return your foundItem to the frontend. Keep in mind that everything you return in this props object will be exposed to the frontend, so don't return any credentials like personal API keys.
Take a look at this: Nextjs App Route Get Ssr Data
Setup for GetStaticPaths()
To set up GetStaticPaths() in your Next.js project, you need to implement the function in your page's code. For JavaScript, you can omit GetStaticPaths as the type for getStaticPaths().
A different take: Next Js Getstaticpaths
The getStaticPaths() function requires a specific form for the paths within the return. You can use two options: an array with an object for every path you want Next.js to pre-render, or path strings like '/test/St2-18', '...', '...'.
You don't need to include every path which should be pre-rendered, especially if you have a large dataset. In this example, we're giving every possible path to getStaticPaths().
To handle manual errors and loading sequences, set the fallback property to true.
Data Fetching and APIs
To fetch data in Next.js dynamic routing, you need an async function called getData(), which will be helpful for getStaticProps() and getStaticPaths() functions. This function will look confusing if you're new to backend JavaScript code, but it's just a matter of reading a JSON file and extracting the data.
The getData() function takes the file path, file data, and data as variables. It targets the current working directory, then the backendData folder, and finally the JSON file. The file data is then converted into usable data.
To fetch the specific data you want to display, you can use the URL to pull the identifier and combine it with the getData() result data. This allows you to search for the specific object containing the data you want to display within your backend's getData() result.
Expand your knowledge: File Upload Next Js Supabase
Creating a Data Fetching Function
Creating a data fetching function is a crucial step in making data accessible to your application. This function is called getData() and it's an async function.
It's designed to be helpful for the getStaticProps() and getStaticPaths() functions, which might look confusing if you're not familiar with backend JavaScript code.
The getData() function targets the current working directory (cwd) and then the backendData folder to access the JSON file. It reads the file and extracts the actual JSON data stored in it.
The function also converts the file data so it can be used in the next steps. The data it provides is from the some-backend-data.json file, which can be utilized in getStaticProps() as well as in getStaticPaths().
The data fetched by the getData() function should differ for each user, as we want to fetch data for specific identifiers like St2-18 and UY-SC.
The function helps reach out to our backend data, but we still need to know which exact data we want to extract from our dummy backend.
This can be done by pulling the specific identifier from the URL and combining it with the extracted getData() result data.
On a similar theme: Getstaticprops Next Js
Rendering REST and GraphQL APIs
Rendering REST and GraphQL APIs is a crucial step in data fetching.
REST, or Representational State of Resource, is a type of API that uses a client-server architecture to manage and manipulate data.
In a REST API, resources are identified by URIs, and operations are performed using HTTP methods like GET, POST, PUT, and DELETE.
Before diving into dynamic routing, it's essential to understand how these APIs work.
GraphQL, on the other hand, is a query language for APIs that allows clients to specify exactly what data they need.
This approach reduces the amount of data transferred between the client and server, making it more efficient.
REST and GraphQL APIs have different approaches to data fetching, but both are widely used in modern web development.
Recommended read: Next Js Restful Api
Data Fetching in
Data Fetching in Next.js with Dynamic Routing is a powerful approach that allows you to create dynamic routes with valid parameters.
Imagine you're building a shop page where you list a bunch of different items, each with a link for more information about that specific item. Dynamic routing is the best approach for such cases.
The getData() function is an async function that will be helpful for the getStaticProps() and getStaticPaths() functions. This function reads a JSON file and extracts the actual JSON data stored in it.
With the getData() function, you can reach out to your backend data and extract the specific data you want to display. You can pull the specific identifier from the URL, for example, St2-18, and combine it with your extracted getData() result data.
The getStaticProps() function successfully extracts the information you need from your URL to search for the specific object in your backend data array. This is done by saving the information in the itemID variable.
On a similar theme: Nextjs Backend
Frequently Asked Questions
Is Next.js static or dynamic?
Next.js offers a hybrid approach, combining static and dynamic rendering capabilities to optimize performance. With Next.js, you can have both static and dynamic routes, allowing for flexible rendering options.
Sources
- https://www.digitalocean.com/community/tutorials/create-dynamic-routes-in-next-js-with-route-guards-and-user-authentication
- https://mariestarck.com/a-beginners-guide-to-dynamic-routing-in-next-js/
- https://javascript.plainenglish.io/different-ways-of-handling-dynamic-routing-in-next-js-312006f5ba1b
- https://mattermost.com/blog/dynamic-routing-in-next-js-using-rest-and-graphql-apis/
- https://www.freecodecamp.org/news/how-to-setup-dynamic-routing-in-nextjs/
Featured Images: pexels.com