Route Parameters & Navigation
React Router Basics dersinde sabit URL'lerle (/courses, /about)
çalıştık. Bu ders, URL'in İÇİNE değişken bir değer koymayı (/courses/java
gibi) ve bir link'e tıklamadan, kod içinden sayfa değiştirmeyi anlatıyor.
Route Parametreleri: URL'den Veri Okumak
/courses/java ve /courses/react gibi URL'ler için ayrı ayrı Route
yazmak yerine, URL'in bir kısmını DEĞİŞKEN olarak tanımlayabiliriz:
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>
);
}
path="/courses/:courseSlug" yazdığımızda, :courseSlug kısmı bir
route parametresi olur -- /courses/java URL'inde courseSlug
"java" değerini alır. Component içinde bu değeri useParams() hook'u
ile okuyoruz; dönen nesnenin anahtarı, Route'taki isimle (courseSlug)
aynı.
İç İçe (Nested) Route'lar ve Outlet
Bazen bir sayfanın İÇİNDE, URL'e göre değişen ALT bir bölüm olur -- örneğin bir kurs sayfasının içinde, seçilen konuya göre değişen bir içerik alanı:
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>
);
}
Bir Route'u başka bir Route'un İÇİNE yazarak (:topicSlug,
:courseSlug route'unun içinde) iç içe (nested) bir yapı kurarız. Üst
component'in (CourseLayout) içine koyduğumuz <Outlet />, eşleşen alt
route'un TAM OLARAK nereye render edileceğini belirtir -- Outlet
olmadan alt route hiçbir yerde görünmez.
useNavigate ile Programatik Yönlendirme
Link, kullanıcının TIKLAMASINI gerektirir. Bazen bir işlemin
SONUCUNDA (bir butona tıklayınca, bir hesaplama bitince) kod içinden
sayfa değiştirmek isteriz:
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>
);
}
useNavigate() hook'u bize bir navigate fonksiyonu verir; bu
fonksiyonu bir event handler İÇİNDEN çağırarak URL'i değiştirebiliriz --
Link'in aksine, bu bir tıklamaya değil, kod içindeki bir KOŞULA
bağlıdır.
Bir İşlemden Sonra Yönlendirmek
useNavigate'in en yaygın kullanımlarından biri, bir form gönderildikten
sonra kullanıcıyı başka bir sayfaya yönlendirmek:
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>
);
}
Form Handling dersinde gördüğümüz onSubmit + preventDefault deseni
burada da aynı -- tek fark, form "gönderildikten" (bu örnekte gerçek bir
kayıt işlemi olmadığı için doğrudan) sonra navigate("/courses") ile
kullanıcıyı kurs listesine yönlendiriyoruz.
Geri Gitmek: navigate(-1)
navigate'e bir URL yerine bir SAYI da verilebilir -- bu, tarayıcı
geçmişinde ileri/geri gitmek için kullanılır:
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), tarayıcının "geri" butonuyla aynı işi yapar: history'de
bir adım geriye gider. Bu, kullanıcıyı belirli bir sayfaya (/courses
gibi) sabitlemek yerine, "neredeyse geldiyse oraya" dönmesini sağladığı
için genellikle "Back" butonlarında tercih edilir.
Özet ve Terimler Sözlüğü
Bir URL'in bir kısmını :isim ile tanımlayarak route parametresi
oluşturabilir, değerini useParams() ile okuyabiliriz. Bir Route'u
başka bir Route'un içine yazıp üst component'e <Outlet /> ekleyerek
iç içe (nested) route'lar kurabiliriz. useNavigate(), bir event
handler içinden ya da bir işlemin sonucunda, tıklamaya gerek kalmadan
sayfa değiştirmemizi sağlar; navigate(-1) ise tarayıcı geçmişinde
geriye gitmek için kullanılır.
Terimler Sözlüğü
Route Parametresi — Bir URL kalıbında :isim ile tanımlanan,
gerçek URL'de değişken bir değer alan kısım.
Nested Route (İç İçe Route) — Başka bir Route'un içine yazılan,
yalnızca üst Route eşleştiğinde ve <Outlet /> konumunda render edilen
Route.
Outlet — Üst (parent) route component'inin içinde, eşleşen alt (child) route'un render edileceği yeri belirten component.
Programatik Navigasyon — Bir link'e tıklamak yerine, kod içinden
(örneğin bir event handler'dan) useNavigate() ile sayfa değiştirmek.
Pratik Proje
Bu kategoride (React Router Basics, Route Parameters & Navigation)
öğrendiğimiz kavramları bir arada kullanan, gerçek ve çalıştırılabilir
bir örnek proje var:
Routing Demo
-- öğrenme platformunun kendi kurs yapısına benzeyen küçük bir kurs
gezinme uygulaması (/courses, /courses/java, /courses/java/enum
gibi).
Proje; BrowserRouter + Routes + Route ile sayfa tanımlamayı,
Link/NavLink ile gezinmeyi, route parametreleriyle (useParams)
URL'den veri okumayı, Outlet ile iç içe route'ları ve useNavigate
ile programatik yönlendirmeyi bir arada gösteriyor. Bilgisayarına
indirip çalıştırabilir, kodunu satır satır inceleyebilirsin:
git clone https://github.com/cdurgun/react-course-projects.git
cd react-course-projects
npm install
cd projects/routing
npm run dev
react-course-projects deposu npm workspaces kullanır -- npm install
yalnızca bir kez, depo kökünde çalıştırılır ve tüm proje klasörleri ortak
bağımlılıkları paylaşır (her klasörde ayrı bir node_modules oluşmaz). Kök
dizinde npm install'ı daha önce çalıştırdıysan, doğrudan
cd react-course-projects/projects/routing yapıp npm run dev demen
yeterli.