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.

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>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:

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:

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

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-domkullanabilirsiniz. Bir mobil uygulama geliştiriyorsanızreact-router-native kullanabilirsiniz.

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

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

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> 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, BrowserRouterbileşenini içe aktaralım:

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 historynesnesi 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.pushve 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.goBackve history.goForward gibi yöntemlerdir.

Link ve Route

<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.

Burada, HomeCategoryveProductsbileşenlerini oluşturmuş olduk. Şimdilik bir sorun yok gibi gözüküyor olabilir ancak, bileşenlerin kapladığı alan ve içeriği büyüdükçe, her bileşen için ayrı dosyalar hazırlamak daha iyi olacaktır. Kendimden örnek vemem gerekirse; genelde bir kural olarak, 15-20 kod satırından fazla yer kaplayan bir bileşen için yeni bir dosya oluşturmaya çalışıyorum. İlerleyen örneklerde de App.js dosyasına sığamayacak kadar büyük olan bileşenler için ayrı bir dosya oluşturacağım.

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:

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 vehistory 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:

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

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

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

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:

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:

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:

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:

Burada, match nesnesine erişim sağlamak için useRouteMatch kancasını kullanıyoruz. Daha önce belirttiğimiz gibi, match.urliç içe bağlantılar oluşturmak için, match.pathise 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.

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. :nameise 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 paramsnesne oluşturacaktır:

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:

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.

İ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:

İ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:

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:

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:

Birisi /admin oturumu kapalıyken rotaya erişmeye çalışırsa, rota yeniden /login ‘e yönlendirilecektir. Geçerli konum hakkındaki bilgiler stateprop 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çerisindePrivateRoute.jsisimli bir dosya oluşturun. Bu dosyayı aşağıdaki gibi düzenleyin:

Gördüğünüz gibi, işlev tanımında aldığımız eşyaları bir Componentprop ve bir restprop olarak dönüştürüyoruz. Componentprop, <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 veisAuthenticated‘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:

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:

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 falseolarak 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!

Paylaşmak İster Misiniz?