Ders İçeriği

React Router Nedir? Neden Kullanılır?

React Router, React uygulamalarında sayfa yönlendirmesi (routing) yapmak için kullanılan en popüler kütüphanedir. Tek sayfa uygulamalarında (SPA) farklı URL'lere göre farklı bileşenleri göstermek ve kullanıcının tarayıcı geçmişini yönetmek için kullanılır.

React Router'ın temel amacı, kullanıcıların URL değişikliklerini yaşayabilmesi ve bu değişikliklere göre uygun içeriğin gösterilmesidir. Geleneksel web sitelerinde her sayfa için ayrı HTML dosyası bulunurken, React uygulamalarında tek bir HTML dosyası vardır ve içerik JavaScript ile dinamik olarak değiştirilir.

Neden React Router Kullanmalıyız?

Tek sayfa uygulamalarında navigasyon yapmak için React Router kullanmak birçok avantaj sağlar. İlk olarak, kullanıcı deneyimi açısından sayfa geçişleri çok daha hızlı olur çünkü tüm sayfa yeniden yüklenmez, sadece gerekli bileşenler değiştirilir. Bu, özellikle büyük uygulamalarda performans açısından önemli bir avantajdır.

İkinci olarak, tarayıcının geri ve ileri butonları doğal olarak çalışır. Kullanıcılar alışık oldukları şekilde navigasyon yapabilir ve sayfa geçmişi korunur. Bu, kullanıcı deneyimi açısından kritik bir özelliktir.

Üçüncü olarak, URL'ler anlamlı hale gelir ve kullanıcılar belirli sayfaları bookmark yapabilir veya doğrudan link paylaşabilir. Bu, SEO açısından da önemlidir çünkü arama motorları farklı sayfaları indexleyebilir.

Son olarak, React Router kod organizasyonu açısından da faydalıdır. Her rota için ayrı bileşenler oluşturarak, uygulamanın yapısını daha modüler hale getirebilirsiniz.

Kurulum ve Temel Kullanım

React Router'ı projenize eklemek için npm veya yarn kullanarak kurulum yapmanız gerekir. En yaygın kullanılan paket react-router-dom'dur çünkü web uygulamaları için özel olarak tasarlanmıştır.

npm install react-router-dom

Kurulumdan sonra, React Router'ı kullanmaya başlamak için öncelikle uygulamanızın kök bileşenini bir Router ile sarmallamanız gerekir. En yaygın kullanılan router türü BrowserRouter'dır.

import React from 'react';

import ReactDOM from 'react-dom/client';

import { BrowserRouter } from 'react-router-dom';

import App from './App';


const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(

  <BrowserRouter>

    <App />

  </BrowserRouter>

);

Bu kurulumdan sonra, uygulamanızın herhangi bir yerinde React Router'ın bileşenlerini kullanabilirsiniz. Temel routing yapısı Routes ve Route bileşenleri ile oluşturulur.

import React from 'react';

import { Routes, Route } from 'react-router-dom';

import Home from './components/Home';

import About from './components/About';

import Contact from './components/Contact';


function App() {

  return (

    <div className="App">

      <Routes>

        <Route path="/" element={<Home />} />

        <Route path="/about" element={<About />} />

        <Route path="/contact" element={<Contact />} />

      </Routes>

    </div>

  );

}


export default App;

Bu basit örnekte, üç farklı rota tanımlanmıştır. Kullanıcı ana sayfaya gittiğinde (/) Home bileşeni, /about sayfasına gittiğinde About bileşeni ve /contact sayfasına gittiğinde Contact bileşeni gösterilecektir.

Route, Link, NavLink Bileşenleri

React Router'da navigasyon yapmak için çeşitli bileşenler bulunur. Bu bileşenlerin her biri farklı amaçlar için kullanılır ve kendine özgü özellikleri vardır.

Route Bileşeni

Route bileşeni, belirli bir URL yolu ile bir React bileşenini eşleştirmek için kullanılır. Her Route bileşeni en az iki prop alır: path ve element.

<Route path="/products" element={<ProductList />} />

Route bileşeninin birçok farklı kullanım şekli vardır. Örneğin, varsayılan rota için path prop'u olmayan bir Route kullanabilirsiniz:

<Routes>

  <Route path="/" element={<Home />} />

  <Route path="/about" element={<About />} />

  <Route path="*" element={<NotFound />} />

</Routes>

Burada * joker karakteri, tanımlanmamış tüm rotalar için kullanılır ve genellikle 404 sayfası göstermek için kullanılır.

Link Bileşeni

Link bileşeni, uygulamanızda navigasyon linkleri oluşturmak için kullanılır. HTML'deki <a> etiketinin React Router versiyonu olarak düşünülebilir, ancak sayfa yeniden yüklenmesine neden olmaz.

import { Link } from 'react-router-dom';


function Navigation() {

  return (

    <nav>

      <ul>

        <li><Link to="/">Ana Sayfa</Link></li>

        <li><Link to="/about">Hakkımızda</Link></li>

        <li><Link to="/contact">İletişim</Link></li>

      </ul>

    </nav>

  );

}

Link bileşeni, to prop'u ile hedef URL'yi belirtir. Kullanıcı bu linke tıkladığında, sayfa yeniden yüklenmeden ilgili bileşen gösterilir.

Link bileşenine ek özellikler de ekleyebilirsiniz:

<Link 

  to="/products" 

  state={{ from: 'homepage' }}

  replace={true}

>

  Ürünler

</Link>

Burada state prop'u ile hedef bileşene veri gönderebilir, replace prop'u ile tarayıcı geçmişine yeni bir giriş eklemek yerine mevcut girişi değiştirebilirsiniz.

NavLink Bileşeni

NavLink bileşeni, Link bileşeninin gelişmiş bir versiyonudur ve aktif link durumunu yönetmek için ek özellikler sunar. Genellikle navigasyon menülerinde kullanılır.

import { NavLink } from 'react-router-dom';


function Navigation() {

  return (

    <nav>

      <NavLink 

        to="/" 

        className={({ isActive }) => isActive ? 'active' : ''}

      >

        Ana Sayfa

      </NavLink>

      <NavLink 

        to="/about"

        style={({ isActive }) => ({

          color: isActive ? 'red' : 'blue'

        })}

      >

        Hakkımızda

      </NavLink>

    </nav>

  );

}

NavLink bileşeni, mevcut URL ile eşleştiğinde otomatik olarak active sınıfını ekler veya özel stil uygular. Bu, kullanıcının hangi sayfada olduğunu görsel olarak belirtmek için çok kullanışlıdır.

Dinamik Rotalar ve Parametreler

Gerçek dünya uygulamalarında, statik rotalar yeterli olmaz. Örneğin, bir e-ticaret sitesinde her ürün için ayrı rota tanımlamak pratik değildir. Bu durumda dinamik rotalar kullanılır.

URL Parametreleri

URL parametreleri, rota tanımında : karakteri ile belirtilir:

<Routes>

  <Route path="/user/:id" element={<UserProfile />} />

  <Route path="/product/:category/:id" element={<ProductDetail />} />

</Routes>

Bu parametrelere bileşen içinde useParams hook'u ile erişebilirsiniz:

import { useParams } from 'react-router-dom';


function UserProfile() {

  const { id } = useParams();

  

  return (

    <div>

      <h1>Kullanıcı Profili</h1>

      <p>Kullanıcı ID: {id}</p>

    </div>

  );

}


function ProductDetail() {

  const { category, id } = useParams();

  

  return (

    <div>

      <h1>Ürün Detayı</h1>

      <p>Kategori: {category}</p>

      <p>Ürün ID: {id}</p>

    </div>

  );

}

Query String Parametreleri

URL'deki query string parametrelerine erişmek için useSearchParams hook'u kullanılır:

import { useSearchParams } from 'react-router-dom';


function ProductList() {

  const [searchParams, setSearchParams] = useSearchParams();

  

  const category = searchParams.get('category');

  const sortBy = searchParams.get('sort');

  

  const updateFilter = (newCategory) => {

    setSearchParams({ category: newCategory, sort: sortBy });

  };

  

  return (

    <div>

      <h1>Ürün Listesi</h1>

      <p>Kategori: {category}</p>

      <p>Sıralama: {sortBy}</p>

      <button onClick={() => updateFilter('electronics')}>

        Elektronik

      </button>

    </div>

  );

}

Programatik Navigasyon

Bazen kullanıcı etkileşimi olmadan, kod içinde navigasyon yapmak gerekebilir. Bu durumda useNavigate hook'u kullanılır:

import { useNavigate } from 'react-router-dom';


function LoginForm() {

  const navigate = useNavigate();

  

  const handleLogin = async (credentials) => {

    try {

      await login(credentials);

      navigate('/dashboard');

    } catch (error) {

      console.error('Giriş başarısız:', error);

    }

  };

  

  const goBack = () => {

    navigate(-1); // Bir önceki sayfaya git

  };

  

  return (

    <div>

      <form onSubmit={handleLogin}>

        {/* Form alanları */}

      </form>

      <button onClick={goBack}>Geri</button>

    </div>

  );

}

Nested Rotalar

Büyük uygulamalarda, rotaları hiyerarşik olarak organize etmek gerekebilir. React Router, iç içe rotalar (nested routes) özelliği ile bu ihtiyacı karşılar.

function App() {

  return (

    <Routes>

      <Route path="/" element={<Layout />}>

        <Route index element={<Home />} />

        <Route path="about" element={<About />} />

        <Route path="products" element={<Products />}>

          <Route index element={<ProductList />} />

          <Route path=":id" element={<ProductDetail />} />

          <Route path="categories" element={<Categories />} />

        </Route>

      </Route>

    </Routes>

  );

}

Bu yapıda, Layout bileşeni tüm sayfalar için ortak olan kısımları (header, footer, sidebar vb.) içerir. Alt rotalar, Outlet bileşeni ile gösterilir:

import { Outlet } from 'react-router-dom';


function Layout() {

  return (

    <div>

      <header>

        <nav>

          <Link to="/">Ana Sayfa</Link>

          <Link to="/about">Hakkımızda</Link>

          <Link to="/products">Ürünler</Link>

        </nav>

      </header>

      

      <main>

        <Outlet />

      </main>

      

      <footer>

        <p>&copy; 2024 Şirket Adı</p>

      </footer>

    </div>

  );

}


function Products() {

  return (

    <div>

      <h1>Ürünler</h1>

      <nav>

        <Link to="/products">Tüm Ürünler</Link>

        <Link to="/products/categories">Kategoriler</Link>

      </nav>

      <Outlet />

    </div>

  );

}

Index Routes

Index route'lar, parent route'un varsayılan içeriğini belirtmek için kullanılır. Yukarıdaki örnekte, /products URL'sine gidildiğinde ProductList bileşeni gösterilir çünkü index route olarak tanımlanmıştır.

Relative Paths

Nested route'larda, relative path'ler kullanarak daha temiz kod yazabilirsiniz:

function Products() {

  return (

    <div>

      <h1>Ürünler</h1>

      <nav>

        <Link to=".">Tüm Ürünler</Link> {/* /products */}

        <Link to="categories">Kategoriler</Link> {/* /products/categories */}

        <Link to="../about">Hakkımızda</Link> {/* /about */}

      </nav>

      <Outlet />

    </div>

  );

}

Route Guards ve Korumalı Rotalar

Gerçek uygulamalarda, bazı sayfaların sadece belirli koşullarda erişilebilir olması gerekir. Örneğin, kullanıcı girişi yapmış olmalı veya belirli yetkilere sahip olmalıdır.

import { Navigate, useLocation } from 'react-router-dom';


function ProtectedRoute({ children }) {

  const isAuthenticated = useAuth(); // Özel hook

  const location = useLocation();

  

  if (!isAuthenticated) {

    return <Navigate to="/login" state={{ from: location }} replace />;

  }

  

  return children;

}


function AdminRoute({ children }) {

  const { user } = useAuth();

  

  if (!user || user.role !== 'admin') {

    return <Navigate to="/unauthorized" replace />;

  }

  

  return children;

}


// Kullanımı

function App() {

  return (

    <Routes>

      <Route path="/login" element={<Login />} />

      <Route path="/dashboard" element={

        <ProtectedRoute>

          <Dashboard />

        </ProtectedRoute>

      } />

      <Route path="/admin" element={

        <AdminRoute>

          <AdminPanel />

        </AdminRoute>

      } />

    </Routes>

  );

}

Error Boundaries ve Hata Yönetimi

React Router v6.4 ve sonrasında, route seviyesinde hata yönetimi için errorElement prop'u kullanılabilir:

function App() {

  return (

    <Routes>

      <Route 

        path="/" 

        element={<Layout />}

        errorElement={<ErrorPage />}

      >

        <Route index element={<Home />} />

        <Route 

          path="products/:id" 

          element={<ProductDetail />}

          errorElement={<ProductError />}

        />

      </Route>

    </Routes>

  );

}


function ErrorPage() {

  const error = useRouteError();

  

  return (

    <div>

      <h1>Bir hata oluştu!</h1>

      <p>{error.statusText || error.message}</p>

    </div>

  );

}

Lazy Loading ve Code Splitting

Büyük uygulamalarda performansı artırmak için, rotaları lazy loading ile yükleyebilirsiniz:

import { lazy, Suspense } from 'react';


const Home = lazy(() => import('./components/Home'));

const About = lazy(() => import('./components/About'));

const Products = lazy(() => import('./components/Products'));


function App() {

  return (

    <Suspense fallback={<div>Yükleniyor...</div>}>

      <Routes>

        <Route path="/" element={<Home />} />

        <Route path="/about" element={<About />} />

        <Route path="/products/*" element={<Products />} />

      </Routes>

    </Suspense>

  );

}

React Router, modern React uygulamalarının vazgeçilmez bir parçasıdır. Doğru kullanıldığında, kullanıcı deneyimini önemli ölçüde artırır ve uygulamanızın profesyonel görünmesini sağlar. Bu ders boyunca öğrendiğiniz kavramları kendi projelerinizde uygulayarak deneyim kazanmanız önemlidir.