Photo by Jason Leung on Unsplash

FRONTEND KAPSAM

Remix Nedir ? (Part-1 Fetching)

Remix React ile Full stack web development için geliştirilmiş React Router üzerine Fetch mekanizması ile ClientSide ve ServerSide Rendering birlikte optimize şekilde ve daha az kod yazarak uygulama geliştirmenizi sağlar.

Onur Dayıbaşı
Frontend Development With JS
6 min readJun 1, 2022

--

Bu yazıda When To Fetch: Remixing React Router — Ryan Florence videosu üzerinden Remix analiz edeceğiz.

Remix yazan ekip aslında React Router geliştiricileri Ryan Florence ve Micheal Jackson. 2014 yılında Ember’e benzer bir router yapısını React getirmek için başlıyorlar. 2022 yılında 3.4 M kişi tarafından kullanılıyor toplamda haftalık 9M download rakamlarına ulaşıyor.

Uygulamalarda Client(Tarayıcının) sunucu ile iletişim halinde olduğu her yerde spinner görmek mümkün. Spinner kullanıcıya bir işlem nedeniyle beklendiğini iletiyor ve ekranda başka işlemler yapmasını engelliyor.

Ryan Florance üzerinde çokça durduğu konuda bu, Fetching işlemleri sırasında gösterilen Spinner ve Loading… konuları.

Uygulamalarda Spinner ve Loading…

Bunun mevcut durumdaki yapısını incelediğimizde, problem olmayan bir durum için useFetch Hook içerisinde durumu handle etmeye çalışırız. Bu kısımda da useEffect async function desteklemediği için sağdaki şekilde yazmanız gerekiyor.

useFetch fonksiyonu (from When To Fetch: Remixing React Router — Ryan Florence)

Peki Error durumlarını nasıl handle edeceğiz. Koda bir çok yere try/catch bloğu ekleme ve if ile hata kodlarını kontrol etmeniz gerekiyor.

Fetching Error Handling (from When To Fetch: Remixing React Router — Ryan Florence)

Çok hızlı ekran linklerine bastığınızda ekranda hem flicker oluşur, hemde bazen yanlış state kalabilir. Bu durumlarda hatalı ara state kalmamak için sadece oluşan hataları ele almak yeterli olmaz, yaptığınız işlemlerin iptal (Abort/Cancellation ) edebiliyor olmanız çok önemlidir.

Fetching Abort when Error Exist (from When To Fetch: Remixing React Router — Ryan Florence)

Yukarıda bir veri çekilemediğinde aynı adımın tekrar işletilmesi için refetch mekanizmasının işletilmesi gerekir, bazen sunucudaki verinin cachelenmesi, bazende verinin tekrar çekilmesi veya verinin çekilmesi sırasında oluşan hataları düzeltici mekanizmalar olması gerekir.

Bu konularda en başarılı kütüphanelerden biriside React-Query kütüphanesidir. React-Query yazısında bu konseptlerden bahsetmiştik

React-Query useQuery.. (from When To Fetch: Remixing React Router — Ryan Florence)

Benzer mekanikleri Redux ile de implement edebilirsiniz. Zaten proje gereksinimleri size bu tarz logicleri implement ettirmeyi zorunlu kılıyor.

Örneğin:

  • Thundra APM ürününde verinin tutulması ve çekilmesi sırasında ekranlarda hep bu 3 state durumu kontrol ediliyordu. Fetching, Fetched, Error … Tabi bu durumları şöyle detaylandırmak mümkün. Fetched edilmiş verinin içerisinde ekstra veri yoksa ekranda No-Data gösterme state ekleyebilirsiniz. Veya Nested veya Master/Slave dediğimiz ekran yapılarında bir fetch işlemi sonrasında yeni fetch işleminin çağrımının gerçekleştirilmesi.
  • Sidekick ürününde ise Debugging için Broker ile konuşan Real Time status ve verileri WebSocket üzerinden sistemdeki mevcut fetched edilmiş veriler ile birlikte işleyebilecek UI State Management yine Redux üzerinden yönetebilecek katmanları kendiniz yazabilirsiniz. Veya ekranda bir Tracepoint ve LogPoint eklerken bunları Optimistic Update ile gerçekleştirme ihtiyacınız olabilir.
  • Thundra Foresight ürününde GitHub Actions workflow run ve çalıştırılan Test Result gösterilmesinde, verinin kendi içerisinde bir bütün olup, tekrar tekrar değişmemesi nedeniyle cacheleme mekaniklerini yine Redux üzerinden çözmeniz gerekebilir.
  • Dynamic Store Kavramı yani yeni store yapılarının benzerlerini on the fly oluşturabilme, bunu Redux yapısı üzerine nasıl inşaa edebilirsiniz Örneğin Make React Apps More Dynamic

Tüm yukarıdaki durumlar ve fazlası size soyutlanmış bir şekilde React-Query içerisinde sunuluyor. Ama siz bu ihtiyaçlarınızı Redux üzerine kendi katmanlarınızı yazarak inşaa edebilir veya Redux üzerinde inşaa edebilmiş RTK-Query ile bu sorunlarınızı çözebilirsiniz.

Tüm bunları kod olarak güzel bir katman veya React-Query gibi bir kütüphane ile soyutlasanız ve basitleştirsenizde kullanıcının gördüğü Loading ve Spinner kavramlarından kurtulamazsınız.

Uygulamalarda Spinner ve Loading… (from When To Fetch: Remixing React Router — Ryan Florence)

Problem Neden Kaynaklanıyor ?

Component Fetching. (Bileşenin Ekranda Render Edilebilecek şekilde hazır hale gelecek şekilde HTML, JS, Styling ve Data yani verisinin hazır olmaması

Bunların parça parça Waterfall(Şelale) yöntemi ile çekilerek uzun bir süre sonra Tarayıcıda hazır hale gelmesi.

Mekanizma aslında basit. Bir URL üzerinden veri çekilir. Bu veri tarayıcı tarafından okunarak Renderlenmek üzere React iletilir.

Initiation, Reading and Fallback Render.. (from When To Fetch: Remixing React Router — Ryan Florence)

Bu işlemlerden bir çok olduğunu ve bir url gelecek veriye diğer fetch işleminde ihtiyaç duyduğunuzu düşünün. Bu durumda Parent Fallback , buna bağlı child fetch işlemini başlatmasını bloklar.

(from When To Fetch: Remixing React Router — Ryan Florence)

Çözüm

Bu durumu engellemenin yöntemi ise bu işlemleri olabildiğince paralel hale getirebilmektir.

Parallel bir Şekilde İşlemleri İlerletmek (from When To Fetch: Remixing React Router — Ryan Florence)

Yani fetch initiation işlemlerini render öncesinde gerçekleştirebilirsek. Component render sırasında ara Loading state oluşmasını engellemiş oluruz. Bunu nasıl yapacağız

Nasıl ?

Bunu gerçekleştirmenin yöntemi yani → fetch initiation render öncesinde yapabilmenin yöntemi bu işlemleri birbirinden ayrıştırmak, bağımlılıklarını ortadan kaldırmak.

  • Initiating fetches
  • reading results
  • rendering fallbacks
Decouple… (from When To Fetch: Remixing React Router — Ryan Florence)

Bu sunumda React 18 bu tip sorunları çözdüğü ile ilgili kısımlara Ryan yorumları temelde;

React is an Rendering Library not a Data Library cümlesinden ilerliyor. Yani React ın amacı render etme kısmı ile ilgili olduğu, verinin yönetilme kısmını içermediğini ve React 18 veya sonrasında duyurulan RSC (React Server Component) , Streaming ve Suspense yukarıdaki sorunları çözmeyi amaçlayan bir yapıda olmadığını anlatıyor.

Özetle React Fallback Rendering odaklanmış bir kütüphane.. (from When To Fetch: Remixing React Router — Ryan Florence)

Özetle React Fallback Rendering odaklanmış bir kütüphane, diğer kısımları yönetmesi veya bu beklentiye girmek çok da doğru bir yaklaşım olmaz.

Fetch Initiation Başlaması İçin Ne Gerekiyor ?

Fetch işleminin başlatılabilmesi için elimizde bir URL olması gerekiyor. Bu URL statik oluşturulmuş veya kullanıcının seçimleri doğrultusunda oluşan veri ile Fetch edilen verinin toplamından dinamik oluşturulmuş bir URL de olabilir.

Sonuç itibari ile Fetch işleminin başlatılması için statik veya dinamik oluşturulmuş URL ihtiyaç duyarız.

Aşağıdaki işlemde Route içerisinde Fetch işlemini ve buna bağlı Component içerisinde useLoaderData().. ile gelen verinin render edileceğini görebilirsiniz.

(from When To Fetch: Remixing React Router — Ryan Florence)

Burada;

  • Route ve loader mekanizması Fetch Initiation gerçekleştirirken
  • useLoaderData → read işlemini
  • InvoiceView …. fallback render gerçekleştirir.

Nested UI

İç içe birbiri ile ilişkili UI geliştirmelerinde buna uygun Nested Route yapılarınızında olması gerekir. Bu konuyu söyle katılıyorum. UI Geliştirmeye öncelikle URL üzerinden Route tanımlayarak başlamalısınız ve UI yapılarınız Route mekanizmasını etkileyecektir.

Nested UI Nedir ?

İç içe birbirine bağımlı Context oluşan UIdır. Örneğin aşağıdaki resimde

  • User Seviyesidir…. Bu seviyede kullanıcının ulaşabileceği sekmeler bulunur; Örneğin Dashboard, Account …
  • Sales Sekme Seviyesidir… Aşağıdaki örnekte kullanıcı Sales sekmesini seçmiştir. bu örnekte olduğu gibi Sales içerisinde Overview, Subscriptions, Invoices vb.. sekmeler bulunur
Root URL (example.com), Sales Tab (example.com/sales). (from When To Fetch: Remixing React Router — Ryan Florence)
  • Invoices sekmesinin sekmesidir. .. Invoice listelerini ve genel bilgileri içerir.
  • Invoice ise spesifik bir invoice ait ekranın olduğu kısımdır.
Invoices Sekmesi (example.com/sales/invoices) veya Invoice Sekmesi (example.com/sales/invoices/1233) (from When To Fetch: Remixing React Router — Ryan Florence)

Bu durumda tüm loading işlemlerini aşağıdaki React Router ile gerçekleştirebilirsiniz.

(from When To Fetch: Remixing React Router — Ryan Florence)

Burada yapılması gereken tüm Fetch işlemlerinin paralel bi şekilde işletilip tüm veri tarayıcıda oluştuktan sonra Rendering işletmektir.

Aşağıdaki tweete tam da bu anlattığım konuyu görselleştirmiş bir örnek bulunuyor. .

Bileşenlerin veri bağımlılıklarını kendilerinin tanımlasını isteriz.

Fetching İşlemi

Fetching işlemi %99 URL segment üzerinden fetch işlemi gerçekleştirilir. Ve bu işlemler sırasında

  • ReactQuery gibi yapılarda bir bileşen içerisinde fetching işleminin başlatıldığını ve akış sonunda tüm state logiclerinin bileşen içerisinde arka arkaya işletildiğini görebilirsiniz.
React-Query vs Remix
  • Remix de ise fetch işlemi bileşenden ayrılarak loader içerisine alınmış ve veri tamamlandığında useLoaderData içerisindeki Invoices tetiklenerek renderlenmesi sağlanıyor. Bu decoupling kısmını React-Router sağlıyor.

Mevcut yöntemlerde Loading işlemi aşağıdaki şekilde Waterfall olarak işletilir.

Remix Decoupling sayesinde fetching işlemlerini paralel bir hale getirerek, ekranda loading spinner daha az gözükmesini sağlar.

Remix Loading …

Referanslar

Okumaya Devam Et 😃

Bu yazının devamı veya yazı grubundaki diğer yazılara erişmek için bu linke tıklayabilirsiniz.

--

--