The Complex Routing Problem
Welcome back everyone. In this video, we will learn yet another routing concept called catch-all segments.
To understand this concept, let's consider scenario number six. Let's assume we are building a documentation site for a project that we have created. The site contains several features, and each feature consists of multiple concepts that need to be explained.
So let's assume our sidenav looks like this: we have five features, and the first feature is expanded to display five concepts. Our goal is to have a unique route for each concept under a given feature. For example, localhost:3000/docs/feature1/concept1, docs/feature1/concept2, docs/feature2/concept1, docs/feature2/concept2, and so on.
Considering we may have 20 features and each feature may have 20 concepts, we end up with a massive 400 routes for our application. And now that you know Next.js has a file system-based routing mechanism, 400 routes correspond to 400 files in our project.
But of course, we can make use of dynamic routing. By replacing the concept files with dynamic route folders using a concept ID, we can reduce the number of files to 20. Similarly, if we replace the feature folder with a dynamic feature ID folder name, we are left with only two folders: the concept ID folder nested inside the feature ID folder.
This approach significantly improves the folder structure. However, we need to keep in mind that for each additional path in the URL, we will require another level of nesting in our app folder. For example, docs/feature1/concept1/example1 would lead to another level of nesting.
Considering that every page in our documentation website shares the same layout, wouldn't it be great if we could define one file that could handle all the route segments in the URL? Well, with Next.js, we can achieve that using the catch-all segments feature. Let's dive into VS Code and understand how it works.
Implementing a Catch-all Route
In the app folder, create a new folder called docs. Within this folder, create another folder. The folder name is special to Next.js. Inside square brackets, use three dots similar to the spread operator in JavaScript and provide a name of your choice. In this case, let's call it slug, which is a common convention when referring to URLs. Inside this folder, create a page.tsx file and add a basic React component.
The component name is Docs, and we return an H1 tag: Docs Home Page. What makes this file special is that it will match any URL that contains the docs segment in the path. Let me demo this in the browser.
If I type localhost:3000/docs/feature1, we see the docs page. Navigating to docs/feature1/concept1 or /example1 also displays the same page.
Accessing and Using Route Segments
As the name suggests, the catch-all segments route captures all URL segments and maps them to this single file in our project. This is particularly useful for documentation where we want different segments for better organization and SEO, but the layout of the document remains the same. We define it once but render it for multiple variations of the URL.
Of course, this feature is only useful if we can access the different segments in the URL. Let me show you how to achieve that. Once again, we rely on the params object provided by Next.js. Destructure it from props and specify the type. This time, slug is an array of strings. We can have multiple route parameters.
For the JSX, we will use an if-else block to handle the different possibilities.
If params.slug.length is equal to 2, we return an H1 tag that says, "Viewing docs for feature {params.slug[0]} since feature ID is the first route parameter and concept {params.slug[1]}".
Else if params.slug.length is equal to 1, we return an H1 tag, "Viewing docs for feature {params.slug[0]}".
If there are no route parameters and slug length is zero, we return "Docs Homepage" as the text.
In the browser, navigate to /docs/routing, and we see the text "Viewing Docs for feature routing". Navigate to /docs/routing/catchall-segments and we see the text "Viewing docs for feature routing and concept catch-all segments". The UI logic can be customized according to your needs, depending on how you want to handle the different route segments.
Ideally, you would use the slug array to fetch the corresponding documentation for the feature ID and concept ID. Scenario 6 has been successfully implemented.
Optional Catch-all Segments
Lastly, I want to mention that Next.js provides an optional catch-all route as well. Currently, if I navigate to just /docs, we see a 404 error page. This is taken care of by Next.js. However, if you want to display the same Doc Page, Next.js provides optional catch-all segments.
All you have to do is wrap the square brackets with another pair of square brackets. Now, we do have an error: Cannot read properties of undefined. So, let's add optional chaining. If we head back to the browser, you would see that the same catch-all segments page is rendered for just /docs as well. The last return statement is executed in this case.
Summary and Next Steps
Here is a visualization of catch-all segments. We have the root route, and any path that contains the docs segment will be matched by the page.tsx file within the slug catch-all segment. All right, we have covered quite a bit about Next.js' routing, but we still have a long way to go. We will explore the remaining features in the upcoming videos. Thank you for watching, and I'll see you in the next one.