Dynamic URL Parameters with useParams0%

Dynamic URL Parameters with useParams

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Dynamic URL Parameters with useParams

1. The Need for Dynamic Route Segments

In modern web applications, you cannot hardcode a separate route for every piece of content in your database:

  • /courses/react-for-beginners
  • /courses/django-backend-architecture
  • /courses/data-analysis-mastery

Creating hundreds of static route tags (<Route path="/courses/course-1" />, <Route path="/courses/course-2" />) is impossible.

Instead, routers use Dynamic URL Parameters (denoted with a leading colon :):

Output
/courses/:courseSlug

The :courseSlug segment acts as a wildcard variable that captures whatever string occupies that position in the active URL.

2. Defining Dynamic Routes

In your router definition, place a colon : before the parameter name:

JSX
<Routes>
<Route path="/" element={<Home />} />
<Route path="/courses" element={<CourseCatalog />} />
{/* Dynamic parameter route */}
<Route path="/courses/:courseSlug" element={<CourseDetail />} />
 
{/* Multiple dynamic parameters */}
<Route path="/courses/:courseSlug/lessons/:lessonId" element={<LessonViewer />} />
</Routes>

3. Reading Parameters with the useParams Hook

React Router provides the useParams() hook to extract active URL parameters from inside the rendered component.

useParams() returns an object where keys match the param names defined in your route (:courseSlug -> params.courseSlug):

JSX
import React, { useState, useEffect } from 'react';
import { useParams, Link } from 'react-router-dom';
 
export default function CourseDetail() {
// Extract dynamic segment from URL
const { courseSlug } = useParams();
 
const [course, setCourse] = useState(null);
const [loading, setLoading] = useState(true);
 
useEffect(() => {
async function fetchCourseDetails() {
setLoading(true);
try {
const response = await fetch(`/api/courses/${courseSlug}`);
const data = await response.json();
setCourse(data);
} catch (err) {
console.error('Failed to load course:', err);
} finally {
setLoading(false);
}
}
 
fetchCourseDetails();
}, [courseSlug]); // Re-fetch whenever the URL parameter changes!
 
if (loading) return <div className="spinner">Loading syllabus...</div>;
if (!course) return <p>Course not found.</p>;
 
return (
<div className="course-detail-view">
<Link to="/courses" className="back-link">← Back to Catalog</Link>
<h2>{course.title}</h2>
<p className="description">{course.description}</p>
<h3>Curriculum Modules</h3>
<ul>
{course.modules.map((m) => (
<li key={m.id}>
<Link to={`/courses/${courseSlug}/lessons/${m.slug}`}>
{m.title}
</Link>
</li>
))}
</ul>
</div>
);
}

4. Crucial Hook Rule: Dependency on useParams

Notice line 29: [courseSlug] is included in the useEffect dependency array.

If a user navigates directly from /courses/react-for-beginners to /courses/django-backend, the CourseDetail component does not unmount and remount; only its URL parameter changes! Listing courseSlug in the dependency array guarantees that your data-fetching effect fires again to load the new course data.


Interactive Quiz

Practice Quiz

Question 1
How do you declare a dynamic URL parameter in a React Router <Route> path?
Question 2
What does the useParams() hook return?
Question 3
If the route is /users/:userId/posts/:postId and the active URL is /users/42/posts/108, what will useParams() return?
Question 4
Why must the extracted parameter (e.g. courseSlug) be included in the useEffect dependency array?
Question 5
What data type are the values returned in the useParams object?
Next Lesson

Programmatic Navigation and useSearchParams

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext