React and Next.js are similar in some ways, and different in others. One of those differences is in how both frameworks handle routing. As someone who has used React for most of my career, I was surprised to find how different Next.js routing is from React Routing. Understanding these differences is crucial for developers working with either framework. I will continue to update this article as I learn more about Next routing. But for now, this article will cover the following:
- Declarative vs file-based routing
- Dynamic routing
Before we dive in, it's important to note that routing in React is typically done with React Router Dom, an external library. Next.js, however, has its inbuilt routing capabilities.
Also, this article is written for the HNG internship. It is a three-month-long program where new developers can test themselves. They also offer career services such as recruitment and mentorship. More details here
Okay, let's explore these differences in detail.
Declarative vs File-Based Routing
The first major difference between routing in React and Next.js is how routing is handled.
React Routing
In React, we need to:
- Add BrowserRouter to
index.js
- Declare the Routes component
- Nest each Route component inside Routes
- Add the intended component we want to route to, and the URL to each Route component
Here's an example:
// index.js
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
// App.js
const App = () => {
return (
<div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />} />
<Route path="/blog/:id" element={<BlogPost />} />
</Routes>
</div>
);
};
export default App;
In summary, you have to define each route in React explicitly.
Next.js Routing
Next.js uses a different paradigm. You don't have to define routes explicitly due to Next's file-based routing, which uses the path of the file where your component is located as the URL of that route.
Using the same example as we used for React, our routes in Next.js might look like this:
my-next-app/
├── pages/
│ ├── index.js // Corresponds to "/"
│ ├── about.js // Corresponds to "/about"
│ ├── blog/
│ │ ├── index.js // Corresponds to "/blog"
│ │ └── [id].js // Corresponds to "/blog/[id]"
├── components/
│ ├── Home.js // Component used in pages/index.js
│ ├── About.js // Component used in pages/about.js
│ ├── Blog.js // Component used in pages/blog/index.js
│ ├── BlogPost.js // Component used in pages/blog/[id].js
└── public/
└── ...
Next.js chose this file-based routing approach to simplify the routing process and make it more intuitive. It eliminates the need for a separate routing configuration, reducing boilerplate code and making the project structure more straightforward. This approach aligns well with Next.js's goal of providing a more opinionated and streamlined development experience.
In Next.js, we write our JSX inside About.js
and then render it inside its route, about.js
. This introduces an important design pattern when using Next.js - separating concerns:
// pages/about.js
import About from '../components/About';
export default function AboutPage() {
return <About />;
}
// components/About.js
import React from 'react';
const About = () => {
return <h1>About Page</h1>;
};
export default About;
In summary, Next.js routes are defined based on the component tree and the respective paths.
Dynamic Routing
The declarative approach of React Router and the file-based approach of Next.js impact how dynamic routes are built and executed in both frameworks.
Dynamic Routing in React
In React, you can define a dynamic route by adding a colon to the route URL:
// App.js
const App = () => {
return (
<div>
<Routes>
<Route path="/blog" element={<Blog />} />
<Route path="/blog/:id" element={<BlogPost />} />
</Routes>
</div>
);
};
export default App;
Each blog has a unique URL, so the path is /blog/whatever-the-title-of-the-blog-is
.
Here's how you would use the dynamic parameter in React:
import { useParams } from 'react-router-dom';
const BlogPost = () => {
const { id } = useParams();
return (
<div>
<h1>Blog Post {id}</h1>
{/* Use the id to fetch and display the blog post */}
</div>
);
};
export default BlogPost;
Dynamic Routing in Next.js
Next.js handles dynamic routing differently:
├── pages/
│ ├── blog/ // Corresponds to "/blog"
│ │ └── [id].js // Corresponds to "/blog/[id]"
Next.js indicates that a route should be dynamic by putting a variable inside square brackets. Here's how we might configure this:
import { useRouter } from 'next/router';
const BlogPost = () => {
const router = useRouter(); // Get the router object
const { id } = router.query; // Destructure to get the 'id' from the URL
return (
<div>
<h1>Blog Post {id}</h1>
{/* Use the id to fetch and display the blog post */}
</div>
);
};
export default BlogPost;
Here's what Next.js is doing under the hood:
- Inside the
[id].js
file, we call the useRouter() method. This method reads[id].js
file and saves it as an object. We save the result inside therouter
variable. - Then, we use the
query
function from useRouter to extract a specific part of the object that was generated. In this case, we collect theid
. - Next.js will use that
id
collected as the URL for that route.
Let's see how we would link to this route:
import Link from 'next/link';
const BlogList = ({ blogs }) => {
return (
<div>
<h1>Blog List</h1>
<ul>
{blogs.map((blog) => (
<li key={blog.id}>
<Link href={`/blog/${blog.id}`}>
<a>{blog.title}</a>
</Link>
</li>
))}
</ul>
</div>
);
};
export default BlogList;
We're taking the URL /blog/[id].js
, and replacing it with /blog/${blog.id}
. This way, whatever value blog.id
holds becomes the URL, giving each individual blog its own unique route.
Conclusion
While both React (with React Router) and Next.js provide powerful routing capabilities, they approach it differently. React Router uses a more declarative style, while Next.js leverages file-based routing. Understanding these differences can help developers choose the right framework for their needs and use routing effectively in their applications.
Top comments (0)