React Router Nedir ve Nasıl Kullanılır?

Fatih Küçükkarakurt

Fatih Küçükkarakurt

17 min read

React Router, React için fiili standart yönlendirme kütüphanesidir. Burası biraz kitapsal tanım biliyorum ama bu yazımızda, örnek bir uygulama ile React Router’ı anlaşılabilir bir şekilde işleyeceğiz.

Birden çok görünüme sahip bir React uygulamasında gezinmeniz gerektiğinde, URL’leri yönetmek için bir yönlendiriciye ihtiyacınız olacaktır. React Router, uygulamanızın kullanıcı arayüzünü ve URL’yi senkronize halde tutar.

İçindekiler

  • React Router’a Giriş
  • React Router Kılavuzuna Genel Bakış
  • React Router Kurulumu
  • React Router Temelleri
  • İç İçe Yönlendirme
    • path ve match
    • Nesnelerin Örtülü Geçişi
    • Switch Bileşeni
  • Dinamik İç İçe Yönlendirme
  • Yol Parametreleri ile İç İçe Yönlendirme
  • Rotaları Koruyun
    • Redirect Bileşeni
    • Özel Rotalar
  • Güvenlik Bildirimi
    • Rota Korumasını Uygulayalım
  • Proje Önizlemesi
  • Özet

React Router’a Giriş

React, istemci tarafında oluşturulan tek sayfalı uygulamalar (SPA) oluşturmak için popüler bir kütüphanedir. Bir SPA birden fazla görünüme (diğer bir deyişle sayfalara) sahip olabilir ve geleneksel çok sayfalı uygulamaların aksine, bu görünümler arasında gezinmek, tüm sayfanın yeniden yüklenmesiyle sonuçlanmamalıdır. Bunun yerine, görünümlerin geçerli sayfa içinde, satır içi olarak işlenmesini isteriz. Çok sayfalı uygulamalara alışkın olan son kullanıcı, aşağıdaki özelliklerin bir SPA’da bulunmasını bekler:

  • Her görünümün, o görünümü benzersiz şekilde belirten bir URL’si olmalıdır. Bu, kullanıcının daha sonra başvurmak üzere URL’ye yer işareti koyabilmesi içindir. Örneğin www.ornek.com/urunler
  • Tarayıcının geri ve ileri düğmesi beklendiği gibi çalışmalıdır.
  • Dinamik olarak oluşturulmuş iç içe görünümler de tercihen kendilerine ait bir URL’ye sahip olmalıdır – örneğin ornek.com/urunler/cantalar/101, buradaki 101 ifadesi, ürün kimliğidir.

Yönlendirme ise tarayıcı URL’sini sayfada gösterilenlerle senkronize tutma işlemidir. React Router, yönlendirmeyi bildirimli olarak yapmanıza izin verir. Bildirim temelli yönlendirme yaklaşımı, uygulamanızdaki veri akışını kontrol etmenize olanak tanır. Şöyle ki;

<Route path="/about">
  <About />
</Route>

<Route> Yolunuzun (Route’un) oluşturulmasını istediğiniz herhangi bir yere bileşeninizi yerleştirebilirsiniz. Şunu da belirtmeliyim ki;

React Router’ın Facebook tarafından geliştirilmiş resmi bir yönlendirme çözümü olduğuna dair yaygın bir yanlış kanı vardır. Gerçekte, tasarımı ve sadeliği ile oldukça popüler olan bir üçüncü taraf kitaplığıdır.

React Router Kılavuzuna Genel Bakış

Bu makale farklı bölümlere ayrılmıştır. İlk olarak, npm ile React ve React Router’ı kuracağız. Ardından, bazı React Router temellerine geçeceğiz. React Router’ın farklı kod tanıtımlarını, buradaki örnekler üzerinde bulacaksınız. Bu makalede anlatılan örnekler şunları içerecek:

  • Temel seyir rotası
  • Yuvalanmış yönlendirme
  • Yol parametreleriyle iç içe yerleştirilmiş yönlendirme
  • Korumalı yönlendirme

Bunlara dair bir fikriniz yok ise, merak etmeyin. Okumaya devam ettiğiniz sürece, cevapları bulacaksınız.

React Router Kurulumu

Az sonra anlatacaklarım için temel seviyede JavaScript ve React bilgisine ihtiyacınız olacak. Ayrıca uygulamayı oluşturmak için bilgisayarınızda kurulu olan Node‘un güncel sürümüne ihtiyacınız var. Eğer güncel bir Node sürümüne sahip değilseniz buraya tıklayarak, Node’un ana sayfasından sisteminiz için doğru dosyayı indirin ve güncelleme işlemini tamamlayın. Node, javascript kütüphanelerini yükleyeceğimiz npm ile birlikte gelir. Komut satırına aşağıdaki komutları vererek her ikisinin de doğru kurulup kurulmadığını kontrol edebilirsiniz:

    node -v
    >14.15.1​

    npm -v
    >6.14.8

Bunu yaptıktan sonra Create React App aracıyla yeni bir React projesi oluşturarak işe koyulalım. Bunu global olarak kurabilir ve şu şekilde kullanabilirsiniz:

npx create-react-app react-router-demo

Bu işlem tamamlandığında, yeni oluşturduğunuz dizine geçin:

cd react-router-demo

React Router kitaplığı üç paket içerir:

react-router, yönlendirici için temel pakettir. Diğer ikisi ise kullanılacak ortama özel paketlerdir. Eğer bir web sitesi inşa etmek isterseniz react-router-dom kullanabilirsiniz . Bir mobil uygulama geliştiriyorsanız react-router-native kullanabilirsiniz.

Biz burada örneğimizi bir web sitesi üzerinden vereceğimiz için, react-router-dom kurulumu yapacağız. Bunun için,

npm install react-router-dom

komutu ile react-router-dom yüklemesini gerçekleştirelim. Ardından geliştirme sunucusunu şu şekilde başlatabilirsiniz:

npm run start

Eğer buraya kadar bir problem yok ise, artık React Router yüklü ve harika çalışan bir React uygulamanız var demektir. Bu uygulamayı http://localhost:3000 adresinden görüntüleyebilirsiniz.

React Router Temelleri

Yapmamız gereken ilk şey, <App> bileşenimizi, bir <Router> bileşenine (React Router tarafından sağlanan) sarmalamaktır(Wrap). Tarayıcı tabanlı bir uygulama oluşturduğumuz için, React Router API’den iki tür yönlendirici kullanabiliriz:

Aralarındaki temel fark ise, oluşturdukları URL’lerde daha rahat anlaşılır:

// <BrowserRouter>
http://ornek.com/about

// <HashRouter>
http://ornek.com/#/about

<BrowserRouter> kullanıcı arayüzünü URL ile senkronize tutmak için HTML5 History API‘sini kullanır. <HashRouter> ise, URL’nin karma kısmını (window.location.hash) kullanır. History API’yi desteklemeyen eski tarayıcıları kullanmanız gerekiyorsa, burada <HashRouter> kullanmalısınız. Ancak farklı durumlarda çoğu zaman <BrowserRouter> kullanmak daha iyi bir seçim olacaktır. Bu farklılıklar hakkında daha fazla bilgi edinmek isterseniz, burayı kullanabilirsiniz.

Öyleyse artık, BrowserRouter bileşenini içe aktaralım:

// src/index.js
import React from "react";
import ReactDom from "react-dom";
import App from "./App";
import { BrowserRouter } from "react-router-dom";

ReactDOM.render{
<BrowserRouter>
    <App />
</BrowserRouter>
document.getElementById("root")
);

Yukarıdaki kodun üzerinde biraz durmakta yarar olduğunu düşünüyorum. Tüm bunların ne anlama geldiğini hep beraber inceleyelim:

history

Her <Router> , geçerli konumda( history.location) , geçerli konumu ve bunun yanında bir yığın üzerinde önceki konumları izleyen bir history nesnesi oluşturur. Bu anlaması güç olabilecek cümleyi şöyle açıklayabileceğime inanıyorum. Mevcut konum değiştiğinde, görünüm yeniden oluşturulur ve bir gezinme hissi elde edersiniz. Peki mevcut konum nasıl değişiyor?

history bu olayla ilgilenmek için, history.push ve history.replace gibi yöntemlere sahiptir. <Link> bileşenine tıkladığınızda history.push çağırılır. <Redirect> bileşeninde ise, history.replace . Diğer yöntemler ise, history.goBack ve history.goForward gibi yöntemlerdir.

<Route> bileşeni, React Router konusundaki en önemli bileşendir. Mevcut konumunuz, rotadaki konumla eşleşiyorsa, UI oluşturur.

Uygulamamızın çalışması için gereken bileşenleri ele aldığımıza göre src/App.js üzerinde düzenlemeler yapmaya başlayabiliriz.

import React from 'react';
import { Link, Route, Switch } from 'react-router-dom';

const Home = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Home"></span>Home<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

const Category = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Category"></span>Category<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

const Products = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Products"></span>Products<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

export default function App() {
  return (
    <div>
      <nav className="navbar navbar-light">
        <ul className="nav navbar-nav">
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/category">Category</Link>
          </li>
          <li>
            <Link to="/products">Products</Link>
          </li>
        </ul>
      </nav>

      {/* Yol ozelligi mevcut URL ile eslesirse yol bilesenleri olusturulur */}

      <Route path="/">
        <Home />
      </Route>
      <Route path="/category">
        <Category />
      </Route>
      <Route path="/products">
        <Products />
      </Route>
    </div>
  );
}

Burada dikkat edimesi gereken önemli bir nokta var. / , hem / ile hem de /category ile eşleşecek. Bu nedenle her iki yolda oluşturulacak. Ama bundan kaçınmamız gerekiyor. Ne yapmalıyız? İşte aşağıda bunun için bir çözüm var:

<Route exact path="/">
  <Home />
</Route>

Bir rotanın yalnızca “rota tam olarak doğru” olduğunda kullanılmasını istiyorsanız, exact prop kullanmanız gerekir.

İç İçe Yönlendirme

İç içe geçmiş rotalar oluşturmak için <Route> ‘un nasıl çalıştığını daha iyi anlamamız gerekiyor.

React Router belgelerinde de okuyabileceğiniz gibi , <Route> ile bir şey oluşturmanın önerilen yöntemi, children elementini kullanmaktır. Elbette <Route> ile bir şeyler oluşturmanız için başka yöntemlerde var. Bunlar çoğunlukla, kancalar (hooks) kullanılmadan önce yönlendiricinin önceki sürümleriyle oluşturulan uygulamaları desteklemek için sağlanmıştır:

  • component: URL eşleştiğinde yönlendirici, React.createElement kullanarak verilen bileşenden bir React öğesi oluşturur.
  • render: Satır içi işleme için kullanışlıdır.
  • children: Aslında bu render 'a benzer. Ancak, yolun konumla eşleşip eşleşmediğine bakılmaksızın işlenir.

path ve match

path prop, yönlendiricinin eşleşmesi gereken URL bölümünü tanımlamak için kullanılır. Yol dizesini normal ifadeye dönüştürmek için Path-to-RegExp kütüphanesini kullanır.

Yönlendiricinin yolu ve konumu başarıyla eşleştirilirse, match object adı verilen bir nesne oluşturulur. match object, URL ve URL yolu hakkında daha fazla bilgi içerir. Bu bilgilere, aşağıda listelenen özellikler aracılığıyla erişilebilir:

  • match.url: URL’nin eşleşen kısmını döndüren bir dize. Bu, özellikle yuvalanmış **<Link>bileşeni oluşturmak için kullanışlıdır.
  • match.path: <Route path=""> Bunu iç içe geçmiş <Route> bileşenleri oluşturmak için kullanacağız.
  • match.isExact: Eşleşme aynıysa (sondaki karakterler olmadan) true döndüren bir Boole.
  • match.params: Path-RegExp paketi tarafından ayrıştırılan URL’den, key/value çiftlerini içeren bir nesne.

Nesnelerin Örtülü Geçişi

Bir rotayı işlemek için component props kullanırken, match, location ve history rota temellerinin bileşene dolaylı olarak aktarıldığını unutmayın. Ancak yeni rota oluşturma modelini kullanırken, durum böyle değildir.

Örnek vermek gerekirse, aşağıdaki bileşeni ele alalım:

const Home = (props) => {
  console.log(props);

  return (
    <div>
      <h2>
        <span class="ez-toc-section" id="Home-2"></span>Home<span class="ez-toc-section-end"></span>
      </h2>
    </div>
  );
};

Şimdi ise rotayı şu şekilde oluşturun:

<Route exact path="/" component={Home} />

Ve aşağıdakiler günlüğe kaydedilecektir:

{
 history: { ... }
 location: { ... }
 match: { ... }
}

Ama şimdi bunun yerine rotayı şu şekilde oluşturun:

<Route exact path="/">
  <Home />
</Route>

Ve günlüğe kaydedilenler:

{
}

Bu ilk bakışta dezavantajlı görünebilir ama endişelenmeyin. React v5.1 sürümünden sonra, ihtiyacınız olan şeye, ihtiyaç duyduğunuz yerde erişmenize yardımcı olacak birkaç kanca getirilmiştir. Bu kancalar, yönlendiricimizin durumunu yönetmemiz için bize yeni yollar sunar ve bileşenlerimizi düzeltmek için oldukça yardımcıdır.

Ben buradaki örneklerimde bu kancalardan bazılarını kullanacağım, ancak daha derinlemesine bir bakış istiyorsanız, React Router v5.1 sürüm duyurusuna göz atın . Ayrıca, kancaların React’in 16.8 sürümünde tanıtıldığını, bu yüzden onları kullanmak için en azından bu sürümde olmanız gerektiğini lütfen unutmayın.

switch Bileşeni

Örneklere geçmeden önce, sizi Switch bileşeniyle tanıştırmak istiyorum.

Aşağıdaki kodu incelememiz yararlı olacaktır:

<Route exact path="/"><Home /></Route>
<Route path="/category"><Category /></Route>
<Route path="/products"><Products /></Route>
<Route path="/:id">
 <p>Bu metin herhangi bir rota icin islenecektir '/'</p>
</Route>

URL /products olduğunda /products ile eşleşen tüm rotalar oluşturulur. Bu nedenle, path /:id içeren <Route> , <Products> bileşeni ile beraber oluşturulur. Ancak bunu kullanmak istemezseniz veya bu durumu gerçekleşmesini istemiyorsanız, rotalarınıza <Switch> bileşeni eklemelisiniz. Örnek vermek gerekirse:

<Switch>
  <Route exact path="/">
    <Home />
  </Route>
  <Route path="/category">
    <Category />
  </Route>
  <Route path="/products">
    <Products />
  </Route>
  <Route path="/:id">
    <p>Bu metin, yukarida tanimlananlar disindaki herhangi bir yol icindir.</p>
  </Route>
</Switch>

path ‘in**:id** kısmı dinamik yönlendirme için kullanılır. Eğik çizgiden sonraki her şeyle eşleşecek ve bu değeri bileşende kullanılabilir hale getirecektir. Bir sonraki başlık altında bundan bahsedeceğiz.

Dinamik İç İçe Yönlendirme

Daha önce /, /category ve /products için rotalar oluşturduk. Peki ama /category/shoes şeklinde bir URL yaratmak istersek ne yapmamız gerekiyor?

Öncelikle src/App.js içerisine girin ve burada bir takım güncellemeler yapmaya başlayalım:

import React from 'react';
import { Link, Route, Switch } from 'react-router-dom';
import Category from './Category';

const Home = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Home-3"></span>Home<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

const Products = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Products-2"></span>Products<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

export default function App() {
  return (
    <div>
      <nav className="navbar navbar-light">
        <ul className="nav navbar-nav">
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/category">Category</Link>
          </li>
          <li>
            <Link to="/products">Products</Link>
          </li>
        </ul>
      </nav>

      <Switch>
        <Route path="/">
          <Home />
        </Route>
        <Route path="/category">
          <Category />
        </Route>
        <Route path="/products">
          <Products />
        </Route>
      </Switch>
    </div>
  );
}

Category ‘yi kendi bileşenine taşıdığımızı fark edeceksiniz. İç içe geçmiş rotalarımızın gitmesi gereken yer tam da burasıdır.

Şimdi bir Category.js dosyası oluşturalım:

// src/Category.js
import React from 'react';
import { Link, Route, useParams, useRouteMatch } from 'react-router-dom';

const Item = () => {
  const { name } = useParams();

  return (
    <div>
      <h3>{name}</h3>
    </div>
  );
};

const Category = () => {
  const { url, path } = useRouteMatch();

  return (
    <div>
      <ul>
        <li>
          <Link to={`${url}/shoes`}>Shoes</Link>
        </li>
        <li>
          <Link to={`${url}/boots`}>Boots</Link>
        </li>
        <li>
          <Link to={`${url}/footwear`}>Footwear</Link>
        </li>
      </ul>

      <Route path={`${path}/:name`}>
        <Item />
      </Route>
    </div>
  );
};

export default Category;

Burada, match nesnesine erişim sağlamak için useRouteMatch kancasını kullanıyoruz. Daha önce belirttiğimiz gibi, match.url iç içe bağlantılar oluşturmak için, match.path ise iç içe geçmiş yollar için kullanılacaktır. Eğer bu eşleşme olayını anlamakta zorlanırsanız, console.log(useRouteMatch()) kullanmayı deneyebilirsiniz.

<Route path={`${path}/:name`}>
  <Item />
</Route>

Yukarıdaki kod, bizim dinamik yönlendirme konusundaki ilk doğru adımımız. Rotaları sabit kodlamak yerine, path prop içinde bir değişken kullanmış olduk. :name ise burada bir yol parametresidir ve category/başka bir eğik çizgi ile karşılaşılana kadar her şeyi yakalar. Yani yol adı buradaki gibi (products/running-shoes) bir params nesne oluşturacaktır:

{
  name: 'running-shoes';
}

Bu değere <Item> bileşeni içinde erişmek için , URL parametrelerinin key/value çiftlerinden oluşan bir nesne döndüren, useParams kancasını kullanıyoruz.

Yol Parametreleri ile İç İçe Yönlendirme

Şimdi işleri biraz daha karmaşık hale getirme zamanı. Bir API tarafından aşağıdaki biçimde döndürülen bazı ürün verilerimiz olduğunu varsayalım:

const productData = [
  {
    id: 1,
    name: 'NIKE Liteforce Blue Sneakers',
    description:
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin molestie.',
    status: 'Available'
  },
  {
    id: 2,
    name: 'Stylised Flip Flops and Slippers',
    description:
      'Mauris finibus, massa eu tempor volutpat, magna dolor euismod dolor.',
    status: 'Out of Stock'
  },
  {
    id: 3,
    name: 'ADIDAS Adispree Running Shoes',
    description:
      'Maecenas condimentum porttitor auctor. Maecenas viverra fringilla felis, eu pretium.',
    status: 'Available'
  },
  {
    id: 4,
    name: 'ADIDAS Mid Sneakers',
    description:
      'Ut hendrerit venenatis lacus, vel lacinia ipsum fermentum vel. Cras.',
    status: 'Out of Stock'
  }
];

Aşağıdaki yollar için rotalar oluşturmamız gerektiğini de varsayalım:

  • /products: bu bir ürün listesi görüntülemelidir.
  • /products/:productId: :productId değerine sahip bir ürün varsa, ürün verilerini görüntülemeli, yoksa bir hata mesajı görüntülemelidir.

src/Products.js şeklinde yeni bir dosya oluşturun. Ve bu dosyayı aşağıdaki gibi düzenleyin. Burada ürün verilerini yukarıdan kopyaladığınızdan emin olun.

import React from "react";
import { Link, Route, useRouteMatch } from "react-router-dom";
import Product from "./Product";

const Products = ({ match }) => {
 const productData = [ ... ];
 const { url } = useRouteMatch();/* Her ürün için bir "<li>" öğe dizisi oluşturun */
 const linkList = productData.map((product) => {
     return (
         <li key={product.id}>
         <Link to={`${url}/${product.id}`}>{product.name}</Link>
         </li>
     );
 });

return (
 <div>
     <div>
         <div>
             <h3><span class="ez-toc-section" id="Products-3"></span>Products<span class="ez-toc-section-end"></span></h3>
             <ul>{linkList}</ul>
         </div>
     </div>

     <Route path={`${url}/:productId`}>
         <Product data={productData} />
     </Route>

     <Route exact path={url}>
         <p>Please select a product.</p>
     </Route>

 </div>
 );
};

export default Products;

İlk olarak, URL’yi match nesnesinden almak için useRouteMatch kancasını kullanıyoruz. Ardından, ürünlerimizin her birinin id özelliğini kullanarak, linkList değişkeninde sakladığımız <Links> bileşenlerinin bir listesini oluşturuyoruz.

İlk yol, ürün kimliğininkine karşılık gelen path propunda bir değişken kullanır. Eşleştiğinde, <Product> bileşenini oluşturup ürün verilerimizi iletiriz:

<Route path={`${url}/:productId`}>
  <Product data={productData} />
</Route>

İkinci yol yalnızca, URL /products olduğunda ve hiçbir şey seçilmediğinde işlenecektir.

Şimdi, src/Product.js dosyasını oluşturun ve aşağıdaki gibi düzenleyin:

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

const Product = ({ data }) => {
  const { productId } = useParams();
  const product = data.find((p) => p.id === Number(productId));
  let productData;

  if (product) {
    productData = (
      <div>
        <h3> {product.name} </h3>
        <p>{product.description}</p>
        <hr />
        <h4>{product.status}</h4>
      </div>
    );
  } else {
    productData = <h2> Sorry. Product doesn't exist </h2>;
  }

  return (
    <div>
      <div>{productData}</div>
    </div>
  );
};

export default Product;

find yöntemi, match.params.productIddeğerine eşit bir ID özelliğine sahip nesneyi, dizide aramak için kullanılır. Ürün mevcutsa, productData görüntülenir. Değilse, “Product doesn’t exist” mesajı oluşturulur.

Son olarak ise, <App>bileşeninizi aşağıdaki gibi güncelleyin:

import React from 'react';
import { Link, Route, Switch } from 'react-router-dom';
import Category from './Category';
import Products from './Products';

const Home = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Home-4"></span>Home<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

export default function App() {
  return (
    <div>
      <nav className="navbar navbar-light">
        <ul className="nav navbar-nav">
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/category">Category</Link>
          </li>
          <li>
            <Link to="/products">Products</Link>
          </li>
        </ul>
      </nav>

      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/category">
          <Category />
        </Route>
        <Route path="/products">
          <Products />
        </Route>
      </Switch>
    </div>
  );
}

Bu kod yapısı ile birlikte, tarayıcıda uygulamayı ziyaret ettiğinizde ve “Products” ı seçtiğinizde, işlenmiş bir alt menü göreceksiniz ve bu da ürün verilerini görüntüleyecektir.

Burada biraz oluşturduğunuz uygulama ile denemeler yapabilirsiniz. Nelerin doğru nelerin yanlış çalıştığını incelemenizde yarar var.

Rotaları Koruyun

Pek çok modern web uygulaması için ortak bir gereksinim, sitenin belirli bölümlerine yalnızca oturum açmış kullanıcıların erişebilmesini sağlamaktır. Bir sonraki bölümde, korumalı bir yolun nasıl uygulanacağına bakacağız, böylece biri bu bölgeye erişmeye çalışırsa /admin, şeklinde oturum açması istenir.

Ancak bundan önce, React Router’da ele almamız gereken birkaç olay var.

Redirect Bileşeni

Sunucu tarafı yönlendirmelerde olduğu gibi, React Router’ın Redirect bileşeni geçmiş yığınındaki mevcut konumu yeni bir konumla değiştirecektir. Burada yeni konum to prop tarafından belirtilir. Burada <Redirect> şu şekilde kullanılır:

<Redirect to={{pathname: '/login', state: { from: location }}}

Birisi /admin oturumu kapalıyken rotaya erişmeye çalışırsa, rota yeniden /login ‘e yönlendirilecektir. Geçerli konum hakkındaki bilgiler state prop aracılığıyla iletilir, böylece kimlik doğrulama başarılı olursa, kullanıcı başlangıçta erişmeye çalıştığı sayfaya geri yönlendirilebilir.

Özel Rotalar

Özel bir rota, bir bileşenin içine yerleştirilmiş olan rotayı tanımlamanın süslü bir yoludur. Bir rotanın işlenip işlenmeyeceğine karar vermemiz gerekirse, burada gidilecek yol özel bir rotadan geçmektedir.

src dizni içerisinde PrivateRoute.js isimli bir dosya oluşturun. Bu dosyayı aşağıdaki gibi düzenleyin:

import React from 'react';
import { Redirect, Route, useLocation } from 'react-router-dom';
import { fakeAuth } from './Login';

const PrivateRoute = ({ component: Component, ...rest }) => {
  const location = useLocation();

  return (
    <Route {...rest}>
      {fakeAuth.isAuthenticated === true ? (
        <Component />
      ) : (
        <Redirect to={{ pathname: '/login', state: { from: location } }} />
      )}
    </Route>
  );
};

export default PrivateRoute;

Gördüğünüz gibi, işlev tanımında aldığımız eşyaları bir Component prop ve bir rest prop olarak dönüştürüyoruz. Component prop, <PrivateRoute> öğemizin koruduğu bileşeni ( ki bizim örneğimizde bu, yönetici (admin) oluyor) içerir.

Daha sonra, kullanıcının oturum açıp açmadığına bağlı olarak, korumalı bileşeni oluşturan veya bizi /login yolumuza yönlendiren bir <Route> bileşeni döndürürüz. Bu, burada <Login> bileşeninden içe aktarılan bir fakeAuth.isAuthenticated özelliği tarafından belirlenir.

Bu yaklaşımla ilgili iyi olan şey, daha açıklayıcı olması ve <PrivateRoute> ‘un yeniden kullanılabilir olmasıdır.

Güvenlik Bildirimi

Gerçek bir uygulamada, sunucunuzdaki korumalı bir kaynak için herhangi bir talebi doğrulamanız gerekir . Bunun nedeni, istemcide çalışan herhangi bir şeyin potansiyel olarak tersine mühendislik yapılabilmesi ve üzerinde değişiklik yapılabilmesidir. Örneğin, yukarıdaki kodda kişi sadece React’in geliştirme araçlarını açabilir ve isAuthenticated‘in değerini değiştirebilir, böylece korunan alana erişim sağlayabilir. Elbette bunun yaşanmasını istemezsiniz.

Bir React uygulamasında kimlik doğrulama bir çözüm olabilir. Ancak bunun için bir çözüm yolu daha var. JSON Web Token kullanabilirsiniz. Başarılı bir oturum açma varsayıldığında, istemci JWT’yi (JSON Web Token), korumalı bir kaynak için herhangi bir istekle birlikte bir başlık olarak gönderir. Bu, daha sonra bir yanıt göndermeden önce sunucu tarafından doğrulanacaktır.

Sunucu parolaları düz metin olarak saklamaz. Aksine, onları şifreleyecektir. Buna bcryptjs‘i örnek verebilirim.

Rota Korumasını Uygulayalım

src/App.js dosyanızı açın ve burada hep birlikte biraz değişiklik yapalım:

import React from 'react';
import { Link, Route, Switch } from 'react-router-dom';
import Category from './Category';
import Products from './Products';
import Login from './Login';
import PrivateRoute from './PrivateRoute';

const Home = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Home-5"></span>Home<span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

const Admin = () => (
  <div>
    <h2>
      <span class="ez-toc-section" id="Welcome_admin"></span>Welcome admin! <span class="ez-toc-section-end"></span>
    </h2>
  </div>
);

export default function App() {
  return (
    <div>
      <nav className="navbar navbar-light">
        <ul className="nav navbar-nav">
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/category">Category</Link>
          </li>
          <li>
            <Link to="/products">Products</Link>
          </li>
          <li>
            <Link to="/admin">Admin area</Link>
          </li>
        </ul>
      </nav>

      <Switch>
        <Route exact path="/">
          <Home />
        </Route>
        <Route path="/category">
          <Category />
        </Route>
        <Route path="/products">
          <Products />
        </Route>
        <Route path="/login">
          <Login />
        </Route>
        <PrivateRoute path="/admin" component={Admin} />
      </Switch>
    </div>
  );
}

Görebileceğiniz gibi, dosyanın üstüne bir <Admin> bileşeni ekledik ve <PrivateRoute> öğemizi <Switch> bileşenine dahil ettik. Daha önce belirtildiği gibi, bu özel yol, kullanıcı oturum açmışsa <Admin> bileşenini oluşturacaktır. Aksi takdirde, kullanıcı /login konumuna yönlendirilecektir. Son olarak, <Login> bileşeninin kodu şöyle olacaktır:

import React, { useState } from 'react';
import { Redirect, useLocation } from 'react-router-dom';

export default function Login() {
  const { state } = useLocation();
  const { from } = state || { from: { pathname: '/' } };
  const [redirectToReferrer, setRedirectToReferrer] = useState(false);

  const login = () => {
    fakeAuth.authenticate(() => {
      setRedirectToReferrer(true);
    });
  };

  if (redirectToReferrer) {
    return <Redirect to={from} />;
  }

  return (
    <div>
      <p>You must log in to view the page at {from.pathname}</p>
      <button onClick={login}>Log in</button>
    </div>
  );
}

/* Sahte bir kimlik doğrulama işlevi */
export const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true;
    setTimeout(cb, 100);
  }
};

state özelliğini aldığımız yönlendiricinin location propuna erişmek için useLocation kancasını kullanmış olduk. Ardından, kullanıcının oturum açması istenmeden önce, erişmeye çalıştığı URL için bir değer almak üzere object destructuring kullandık. Bu yoksa, { pathname: "/" } olarak ayarlarız.

Daha sonra redirectToReferrer özelliğini false olarak başlatmak için React’in useState kancasını kullandık. Bu özelliğin değerine bağlı olarak, kullanıcı ya gittikleri yere yönlendirilir (yani, kullanıcı oturum açmıştır) ya da kullanıcıya oturum açması için bir buton sunulur.

Bu buton tıklandığında,fakeAuth.authenticate ‘i true olarak ayarlayan ve (bir geri arama işlevinde) redirectToReferrer değerini true olarak güncelleyen, fakeAuth.authenticate yöntemi yürütülür. Bu, bileşenin yeniden oluşturulmasına ve kullanıcının yeniden yönlendirilmesine neden olur.

Proje Önizlemesi

Özetlemek Gerekirse

Bu makalede gördüğünüz gibi, React Router, daha iyi, bildirimsel yollar oluşturmak için React’i tamamlayan güçlü bir kütüphane. Peki bu makalede neler öğrendik?

  • React Router nasıl kurulur?
  • Yönlendirmenin temelleri ve bazı temel bileşenler <Router>, <Route>ve<Link>
  • Navigasyon ve iç içe geçmiş yollar için minimal bir yönlendirici nasıl oluşturulur?
  • Yol parametreleri ile dinamik rotalar nasıl oluşturulur?
  • React Router’ın kancaları (React Router Hooks) ile nasıl çalışılır?

Diğer yazılar için buraya tıklayabilirsiniz.

Her birinize Mutlu Kodlamalar!

Sağlıcakla Kalın! 💪

Anatoliacode Makale Aboneliği

Bize abone olarak tüm makaleleri ilk siz okuyabilirsiniz. Ayrıca asla reklam veya spam yapmıyoruz.