Dynamic Routing in React with react-router-dom

React has revolutionized frontend development by introducing component-based architectures, and with libraries like react-router-dom, managing routing in single-page applications (SPAs) has become intuitive and powerful. Among the various routing strategies available, dynamic routing plays a vital role in creating flexible, scalable applications—particularly those involving user profiles, product pages, blog articles, or any other content that depends on a unique identifier.

In this blog, we’ll take a deep dive into how dynamic routing works in React using react-router-dom, how to create and navigate to dynamic routes, and how to pass and use route parameters effectively.


What is Dynamic Routing?

Dynamic routing refers to creating routes that can change based on user interaction or application data. Instead of hardcoding every route, dynamic routing allows you to define patterns that match variable segments of a URL.

For example, in a blog application, a post’s detail page might look like this:

/post/hello-world
/post/react-router-tutorial
/post/why-react-is-awesome

Rather than defining a separate route for each post, we can use a dynamic route like:

/post/:slug

Here, :slug is a URL parameter that acts as a placeholder for any post identifier.


Setting Up react-router-dom

First, make sure you have react-router-dom installed:

npm install react-router-dom

Then set up the router in your application:

import { BrowserRouter, Routes, Route } from "react-router-dom"
import Home from "./pages/Home"
import PostDetail from "./pages/PostDetail"

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/post/:slug" element={<PostDetail />} />
      </Routes>
    </BrowserRouter>
  )
}

The /post/:slug route is dynamic—it can match /post/anything, and React Router will extract that slug value for use in your component.


Creating a Dynamic Route Component

Let’s build a simple component to handle dynamic data. Here’s how PostDetail might look:

import { useParams } from "react-router-dom"

export default function PostDetail() {
  const { slug } = useParams()

  return (
    <div style={{ padding: "2rem" }}>
      <h1>Post Detail</h1>
      <p>You’re reading: <strong>{slug}</strong></p>
    </div>
  )
}

The useParams() hook gives access to all route parameters defined in the URL. In this case, slug would be whatever is passed after /post/.


Navigating to Dynamic Routes

To navigate to a dynamic route, you can use the Link component or useNavigate programmatically.

Using <Link>:

import { Link } from "react-router-dom"

function PostList() {
  const posts = [
    { title: "First Post", slug: "first-post" },
    { title: "React Routing", slug: "react-routing" }
  ]

  return (
    <div>
      <h2>Posts</h2>
      <ul>
        {posts.map(post => (
          <li key={post.slug}>
            <Link to={`/post/${post.slug}`}>{post.title}</Link>
          </li>
        ))}
      </ul>
    </div>
  )
}

Using useNavigate:

import { useNavigate } from "react-router-dom"

function GoToPostButton({ slug }) {
  const navigate = useNavigate()

  return (
    <button onClick={() => navigate(`/post/${slug}`)}>
      Go to Post
    </button>
  )
}

This is helpful when you want to navigate in response to user actions, such as form submissions or button clicks.


Multiple Dynamic Parameters

You can define routes with multiple dynamic segments. For example:

<Route path="/user/:userId/post/:postId" element={<UserPost />} />

Access them with:

const { userId, postId } = useParams()

This structure is useful for nested resources or multi-level content.


Using Dynamic Parameters with Fetch Calls

Often, dynamic routes are used to fetch data from a server based on parameters. For example:

import { useEffect, useState } from "react"
import { useParams } from "react-router-dom"

function PostDetail() {
  const { slug } = useParams()
  const [post, setPost] = useState(null)

  useEffect(() => {
    async function fetchPost() {
      const response = await fetch(`/api/posts/${slug}`)
      const data = await response.json()
      setPost(data)
    }

    fetchPost()
  }, [slug])

  if (!post) return <p>Loading...</p>

  return (
    <div>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </div>
  )
}

This is a typical pattern where the component mounts, reads the route param, fetches data, and displays it.


Handling 404s with Unknown Dynamic Routes

Sometimes, the URL may include a dynamic value that doesn’t correspond to real data. You should handle this case to show a fallback message:

if (!post) {
  return <p>Post not found</p>
}

You can also combine this with a custom 404 component using conditional routing or redirects.


Nested Dynamic Routes

React Router allows nesting of routes, including dynamic ones:

<Route path="/user/:userId" element={<UserLayout />}>
  <Route path="profile" element={<UserProfile />} />
  <Route path="settings" element={<UserSettings />} />
</Route>

In this setup, the dynamic :userId is accessible inside nested routes too using useParams().


Route Params vs Search Params

It’s important to distinguish between:

  • Route Params: /product/:id{ id: '123' }
  • Search Params: /product?id=123{ id: '123' }

Use useParams() for route parameters, and useSearchParams() for query parameters:

const [searchParams] = useSearchParams()
const productId = searchParams.get("id")

Real-World Use Cases for Dynamic Routing

Dynamic routing powers many common application features, such as:

  • Blog posts: /post/:slug
  • User profiles: /user/:username
  • Product details: /product/:productId
  • Category listings: /category/:categoryName
  • Pagination: /page/:pageNumber

It’s a key pattern in building scalable SPAs with clean URLs and maintainable route structures.


Conclusion

Dynamic routing with react-router-dom gives your React apps the flexibility to respond to user-driven paths and data-driven content. With route parameters, reusable components, and clean URL structures, you can create powerful and intuitive navigation experiences.

Whether you’re building a blog, e-commerce store, or dashboard, understanding and implementing dynamic routes is essential to building robust and user-friendly applications. By mastering route parameters, useParams, and useNavigate, you unlock the full potential of React Router in real-world applications.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top