Route Parameters & Navigation
In React Router Basics, we worked with fixed URLs (/courses,
/about). This lesson covers putting a variable value INSIDE a URL
(like /courses/java), and changing pages from code without a link
click.
Route Parameters: Reading Data from the URL
Instead of writing a separate Route for /courses/java and
/courses/react, we can define part of the URL as a VARIABLE:
import { BrowserRouter, Routes, Route, Link, useParams } from "react-router";
function CourseList() {
return (
<div>
<h1>Courses</h1>
<Link to="/courses/java">Java</Link>
<Link to="/courses/react">React</Link>
</div>
);
}
function CourseDetail() {
// ":courseSlug" olarak tanımlanan URL parçası, useParams() ile bir
// nesne olarak okunur -- anahtar, Route'taki isimle (courseSlug) aynı.
const { courseSlug } = useParams();
return <h1>Course: {courseSlug}</h1>;
}
function RouteParamExample() {
return (
<BrowserRouter>
<Routes>
<Route path="/courses" element={<CourseList />} />
<Route path="/courses/:courseSlug" element={<CourseDetail />} />
</Routes>
</BrowserRouter>
);
}
Writing path="/courses/:courseSlug" makes :courseSlug a route
parameter -- in the URL /courses/java, courseSlug takes the value
"java". Inside the component, we read this value with the
useParams() hook; the key on the returned object matches the name
used in the Route (courseSlug).
Nested Routes and Outlet
Sometimes a page has an INNER section that changes based on the URL -- for example, a course page with a content area that changes depending on the selected topic:
import { BrowserRouter, Routes, Route, Link, Outlet, useParams } from "react-router";
function CourseLayout() {
// Bu, /courses/:courseSlug ile eşleşen "üst" route. İçindeki <Outlet />,
// eşleşen ALT route'un (varsa) nereye render edileceğini belirtir.
const { courseSlug } = useParams();
return (
<div>
<h1>Course: {courseSlug}</h1>
<Link to={`/courses/${courseSlug}/enum`}>Enum Topic</Link>
<Outlet />
</div>
);
}
function TopicDetail() {
const { courseSlug, topicSlug } = useParams();
return (
<p>
Topic: {topicSlug} (course: {courseSlug})
</p>
);
}
function NestedRouteExample() {
return (
<BrowserRouter>
<Routes>
<Route path="/courses/:courseSlug" element={<CourseLayout />}>
{/* İç içe (nested) Route -- yalnızca /courses/java/enum gibi bir
URL'de, CourseLayout'un İÇİNDEKİ <Outlet /> konumunda render
edilir. */}
<Route path=":topicSlug" element={<TopicDetail />} />
</Route>
</Routes>
</BrowserRouter>
);
}
Writing one Route INSIDE another (:topicSlug inside the
:courseSlug route) creates a nested structure. The <Outlet /> we
place inside the parent component (CourseLayout) marks EXACTLY where
the matching child route should render -- without Outlet, the child
route wouldn't appear anywhere.
Programmatic Navigation with useNavigate
Link always requires the user to CLICK something. Sometimes we want
to change pages from code AS A RESULT of something -- clicking a
button, finishing a calculation:
import { BrowserRouter, Routes, Route, useNavigate } from "react-router";
function CourseList() {
const navigate = useNavigate();
function handleSelect(courseSlug) {
// Link her zaman bir tıklama gerektirir -- useNavigate() ise, bir
// fonksiyon İÇİNDEN (örneğin bir event handler'dan) URL'i
// DEĞİŞTİRMEMİZİ sağlar.
navigate(`/courses/${courseSlug}`);
}
return (
<div>
<button onClick={() => handleSelect("java")}>Go to Java</button>
<button onClick={() => handleSelect("react")}>Go to React</button>
</div>
);
}
function CourseDetail() {
return <h1>Course Detail</h1>;
}
function UseNavigateExample() {
return (
<BrowserRouter>
<Routes>
<Route path="/courses" element={<CourseList />} />
<Route path="/courses/:courseSlug" element={<CourseDetail />} />
</Routes>
</BrowserRouter>
);
}
The useNavigate() hook gives us a navigate function; calling it
from INSIDE an event handler changes the URL -- unlike Link, this
isn't tied to a click, but to a CONDITION in the code.
Navigating After an Action
One of the most common uses of useNavigate is redirecting the user to
another page after a form is submitted:
import { useState } from "react";
import { BrowserRouter, Routes, Route, useNavigate } from "react-router";
function NewCourseForm() {
const [title, setTitle] = useState("");
const navigate = useNavigate();
function handleSubmit(event) {
event.preventDefault();
// Form gönderildikten (örneğin "kaydedildikten") SONRA, kullanıcıyı
// başka bir sayfaya yönlendirmek yaygın bir kalıptır.
navigate("/courses");
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={title}
onChange={(event) => setTitle(event.target.value)}
placeholder="Course title"
/>
<button type="submit">Save</button>
</form>
);
}
function CourseList() {
return <h1>Courses</h1>;
}
function NavigateAfterActionExample() {
return (
<BrowserRouter>
<Routes>
<Route path="/new-course" element={<NewCourseForm />} />
<Route path="/courses" element={<CourseList />} />
</Routes>
</BrowserRouter>
);
}
The onSubmit + preventDefault pattern from Form Handling is the
same here -- the only difference is that after the form is "submitted"
(directly in this example, since there's no real save operation), we
redirect the user to the course list with navigate("/courses").
Going Back: navigate(-1)
navigate can also be given a NUMBER instead of a URL -- this is used
to move forward or backward in browser history:
import { BrowserRouter, Routes, Route, Link, useNavigate } from "react-router";
function CourseList() {
return (
<div>
<h1>Courses</h1>
<Link to="/courses/java">Java</Link>
</div>
);
}
function CourseDetail() {
const navigate = useNavigate();
function handleBack() {
// navigate(-1), tarayıcının "geri" butonuyla aynı şeyi yapar --
// history'de bir adım geriye gider. navigate(-2) iki adım geriye
// gider, ve benzeri.
navigate(-1);
}
return (
<div>
<h1>Course Detail</h1>
<button onClick={handleBack}>Back</button>
</div>
);
}
function GoBackNavigateExample() {
return (
<BrowserRouter>
<Routes>
<Route path="/courses" element={<CourseList />} />
<Route path="/courses/:courseSlug" element={<CourseDetail />} />
</Routes>
</BrowserRouter>
);
}
navigate(-1) does the same thing as the browser's "back" button: it
goes back one step in history. Since this returns the user to
"wherever they came from" instead of pinning them to a fixed page
(like /courses), it's usually preferred for "Back" buttons.
Summary and Glossary
We can create a route parameter by marking part of a URL with :name,
and read its value with useParams(). Writing one Route inside
another and adding <Outlet /> to the parent component lets us build
nested routes. useNavigate() lets us change pages from inside an
event handler or as a result of some action, without needing a click;
navigate(-1) moves backward in browser history.
Glossary
Route Parameter — A part of a URL pattern marked with :name that
takes a variable value in the real URL.
Nested Route — A Route written inside another Route, rendered only
when the parent Route matches and only at the <Outlet /> position.
Outlet — A component inside a parent route component that marks where the matching child route should render.
Programmatic Navigation — Changing pages from code (e.g. from an
event handler) with useNavigate(), instead of clicking a link.
Practical Project
There's a real, runnable example project that brings together the
concepts from this category (React Router Basics, Route Parameters &
Navigation):
Routing Demo
-- a small course-browsing app that mirrors the learning platform's own
course structure (/courses, /courses/java, /courses/java/enum,
and similar).
It shows defining pages with BrowserRouter + Routes + Route,
navigating with Link/NavLink, reading data from the URL with route
parameters (useParams), nested routes with Outlet, and programmatic
navigation with useNavigate, all working together. You can download
it and run it yourself, and read through the code line by line:
git clone https://github.com/cdurgun/react-course-projects.git
cd react-course-projects
npm install
cd projects/routing
npm run dev
The react-course-projects repo uses npm workspaces -- npm install
only needs to run once, at the repo root, and every project folder
shares the same dependencies (no separate node_modules per folder). If
you've already run npm install at the root, you can just
cd react-course-projects/projects/routing and run npm run dev.