If you've ever built a React app with multiple pages, you're probably familiar with routing. You might have an "About" page at /about
, a "Contact" page at /contact
. These are static routes—simple and predictable.
But what happens when you build an e-commerce site with thousands of products? A blog with hundreds of posts? Or a social network with millions of user profiles? Do we have to create thousands of different Route components? 🤯
The answer is Dynamic Routes—a foundational, powerful concept and the key to building modern, scalable React apps. Let's explore the "magic" behind it!
What are Dynamic Routes? A Simple Explanation 💡
Think of a Dynamic Route as a signpost with a blank space. Instead of pointing to a single fixed address, it points to a type of place, and you can fill in the blank to reach a specific destination.
- Static route:
/about
(Always the About page) - Dynamic route:
/products/:productId
(Could be the page for product with ID1
,123
, orapple-iphone-15
)
The :productId
syntax is the "dynamic" part. It's a parameter you can retrieve and use inside your component. Instead of creating a route for every product, you just need one template route for all product detail pages.
Why Can't We Live Without Dynamic Routes?
Using Dynamic Routes isn't just an option—it's essential for building complex apps. The benefits are huge:
- Scalability: This is the biggest benefit. You only need to write code for a template component, and it can display data for countless different items (products, posts, users, etc.). Your app can grow from 10 products to 10,000 without changing your route structure.
- Clean Code: Instead of a
routes.js
file thousands of lines long or apages
folder with hundreds of component files, you just need a few well-organized template components. - Better UX: Dynamic Routes create clean, meaningful, and shareable URLs (e.g.,
your-site.com/blog/how-to-learn-react-effectively
). Users can bookmark and return to the exact content they viewed. - SEO-Friendly: Search engines like Google prefer clear, keyword-rich URLs. A URL like
/products/samsung-galaxy-s25
is much better than/products?id=789
.
"Hands-on" with React Router DOM 🛠️
The most popular library for routing in React is react-router-dom
. Let's see how to implement Dynamic Routes step by step.
Step 1: Install React Router
If you haven't already, add the library to your project:
npm install react-router-dom
Step 2: Configure a Dynamic Route in App.js
In your main route config file, usually App.js
, use a colon :
before the parameter name to define a dynamic route.
// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import HomePage from './pages/HomePage'
import ProductListPage from './pages/ProductListPage'
import ProductDetailPage from './pages/ProductDetailPage' // Component to display product details
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductListPage />} />
{/* This is our Dynamic Route! */}
<Route path="/products/:productId" element={<ProductDetailPage />} />
</Routes>
</Router>
)
}
export default App
In the example above, :productId
is a placeholder. It will match any value in the URL after /products/
, such as /products/123
or /products/abc
.
Step 3: Get the Dynamic Parameter with the useParams Hook 🎣
So how does the ProductDetailPage
component know which product to display? We'll use the useParams
hook provided by React Router.
useParams
returns an object containing key/value pairs of the URL parameters.
// pages/ProductDetailPage.js
import React from 'react'
import { useParams } from 'react-router-dom'
// Let's say we have an array of product data
const productsData = [
{ id: '1', name: 'iPhone 15 Pro', price: '25,000,000 VND' },
{ id: '2', name: 'Samsung Galaxy S25', price: '23,000,000 VND' },
{ id: '3', name: 'Google Pixel 9', price: '20,000,000 VND' },
]
function ProductDetailPage() {
// Use useParams to get the params object
const params = useParams()
const { productId } = params // Get productId from the object
console.log('Product ID from URL:', productId) // Will log '1', '2', or '3'...
// Find the product in the data array based on productId
const product = productsData.find((p) => p.id === productId)
// Handle the case where the product is not found
if (!product) {
return <h2>Product not found!</h2>
}
return (
<div>
<h1>Product Details</h1>
<h2>{product.name}</h2>
<p>Price: {product.price}</p>
<p>ID: {product.id}</p>
</div>
)
}
export default ProductDetailPage
With just a few lines of code, you have a fully functional product detail page! When a user visits /products/1
, useParams
returns { productId: '1' }
. The component uses this ID to find and display info for "iPhone 15 Pro".
Level Up: Advanced Scenarios 🗺️
Nested Dynamic Routes
You can absolutely nest dynamic routes. For example, to view reviews for a specific product:
<Route path="/products/:productId/reviews/:reviewId" element={<ReviewDetail />} />
In the ReviewDetail
component, useParams
will return an object like { productId: '...', reviewId: '...' }
.
Programmatic Navigation with useNavigate
Sometimes you want to redirect users after an action (e.g., after creating a new product). The useNavigate
hook lets you do this.
import { useNavigate } from 'react-router-dom'
function AddProductForm() {
const navigate = useNavigate()
const handleSubmit = (event) => {
event.preventDefault()
// Logic to add product and get the new product's ID, e.g., newProductId = '4'
const newProductId = '4'
// Redirect the user to the detail page of the newly created product
navigate(`/products/${newProductId}`)
}
// ...
}
Conclusion: Dynamic Routes Aren't Complicated
Dynamic Routes aren't a complicated feature—they're an essential and elegant tool in every React developer's toolkit. By mastering how to define routes with parameters like :id
and how to access those parameters with the useParams
hook, you've unlocked the ability to build large-scale, flexible web apps that deliver a great user experience.
Now, go build your own amazing dynamic apps!