İçeriğe geç

NgRx Nedir? Angular’da NgRx ile State Yönetimi

Merhaba arkadaşlar. Uzun bir aradan sonra, bir süredir üzerinde çalışıp güzel tecrübeler edindiğim ve hala ediniyor olduğum Angular Projelerinde State Yönetimi ve beraberinde NgRx den sizlere bahsetmek istedim. Son derece önemli olan bu konuyu, bu yazımızda NgRx mantığı ile kavramaya çalışacağız.

Angular projelerinde her zaman State ihtiyacımız olmayabilir ama özellikle büyük çaplı projelerde ihtiyaç kaçınılmaz ve hal böyle olunca da State Management konusu karşımıza çıkıyor. Peki en uygun şekilde bu State Yönetimini projemize nasıl uygularız ?

İşte tam bu noktada, biraz araştırmadan sonra NgRx ile tanışıyoruz. NgRx, uygulamalardaki state yönetimi için açık kaynak kodlu bir kütüphanedir.

NgRx Nedir ?

Yukarıda gördüğünüz üzere, “NgRx, popüler state management pattern’i olan Redux’ın, Angular konsept ve tekniklerine uyarlanmış hali, uygulamasıdır” diyebiliriz. Bu kütüphaneyi daha iyi anlamak için, Redux Pattern’ini biraz incelememiz gerekir. Gelin öncelikle Redux’daki akışı inceleyelim.

Redux Pattern

Redux Pattern / Modeli, uygulama boyunca tek yönlü bir veri akışı sağlayarak uygulama state’imizi yönetmemize yardımcı olur.

Adım adım ilerleyelim. Örneğin;

Buradaki checkbox işaretlendiğinde, ürünlerin isimlerinin yanında, ürün kodlarının da görünmesini istiyoruz. İşaretleme sonrası aşağıdaki gibi bir görünüm elde ediyoruz.

Peki kullanıcı sonrasında başka bir sayfaya yönlendiğinde ve geri geldiğinde ne olacak ?Hiçbir şey, son bıraktığı gibi değil, sayfaya ilk geldiğinde gördükleri gibi olacak değil mi ? Yani yaptığı seçimi kaybettik. İşte burada Redux bize yardımcı olabilir.

Aşağıdaki resimde Redux Pattern’in akış diyagramını en temiz ve en net şekilde görmekteyiz.

Bu akış şu şekilde gerçekleşmektedir;

  • View, etkileşime girilen Component’deki bir User Event’i tetiklemek için, Event Binding kullanır.
  • Component bu event’i temsil eden Action‘ı kendi üzerinden dispatch eder yani sözlük anlamı ile sevk eder veya yollar. Action’lar içerisinde “payload” adı verdiğimiz yapıları barındırır. Başka bir deyiş ile kendi üzerinde bir yük taşır ve bu yükü uygun bir yere götürüp bırakmak zorunda 🙂 Yani sevk olduğu yerlere, ihtiyaç olan “tip” yükünü de alır yoluna çıkar. Örneğin yukarıdaki checkbox’ı düşünecek olursak buradaki payload’ımız yani yükümüz “boolean” bir değerdir.
  • Sonrasında bu actionlar “Reducer” dediğimiz yapılara gelir.
  • Reducer’lar, Store (state) dediğimiz yapı üzerinde değişiklik yapabilen, güncelleyebilen fonskiyonlardır diyebiliriz.
  • Store nedir diyecek olursak da eğer; Store, browser’da application’ımızın yaşam süresi boyunca hayatta kalan, in-memory ve anlayacağımız üzere client side bir container’dan başka birşey değildir.
  • Store‘un yapısı değiştirilemezdir yani immutable’dır. Yalnızca mevcut bulunan State içeriği üzerinde Reducer’lar ile güncellemeler yapabiliriz.
  • Sonrasındaki aşama, Selector’ler vasıtası ile Component’lerin ve dolayısı ile de View’ın güncellenmesi olayıdır.
  • Component’ler Selector denilen yapılar ile State’deki değişikliklerden haberdar olurlar.
  • Selector Store’dan neyi alıp, ne tipte, nereye ileteceğini bilen yapılardır. Bu Selectorler’e subscribe olmuş yani onları dinleyen componentlere istediği dataları en güncel haliyle bildirir ve iletirler.

Böyle bir yapımız varken, kullanıcı uygulamamız içerisinde başka bir sayfaya gidip gelirse, State’e bağlı olan Selector ve bu Selector’lere subscribe olmuş Component’ler en güncel State’i elde ederek ekranda en son bıraktığı hali ile kullanıcıyı karşılayacaktır.

Burada sizlere çok basit bir component için yapılan basit bir checkbox kontrolünün arka taraftaki akış mantığını anlatmaya çalıştım 🙂 Şimdi gelelim;

Neden NgRx Kullanmalıyız ?

Aslında mantığına giriş yaptığımız bu yapıyı neden kullanmanız gerektiğini çoktan anladığınızı düşünüyorum. Benim ilk aklıma gelenler ise şu şekilde;

  • Client-Side caching’i bize sağlayan state sayesinde, sürekli servis çağrısı yapmak zorunda kalmamak için,
  • Reducer’lar Store’u günceller, Store’a göre oluşturulmuş Selector’lar ve bu Selector’lara subscribe olmuş tüm Componentlerin güncelleniyor olması için,
  • Kısacası, söz konusu uygulamanın akış şemasını, kullanım örneklerini çıkardığımda, kullanıcının uygulamamda kaldığı süre boyunca bir State’e ihtiyacım olduğu anladığım zaman NgRx kullanımı doğru olacaktır.

NgRx Effects Nedir ?

Angular NgRx kavramındaki Store yaklaşımında olması gereken kavramlardan bir taneside “Efektler”dir.

NgRx Effect’ler, belirli action’ları dinlememizi ve “belirli action birşeyler yaptığında, sende birşeyler yap” mantığı ile çalışan Observable yapılardır.

En basit haliyle bir örnek verecek olursak, “angular uygulamama login olan kullanıcının başarılı şekilde login olup olmadığını dinle, eğer başarılı bir login gerçekleşti ise, payload‘u alıp, kullanıcının user id’si ile mesaj kutusu datalarını getirip güncelle.”

Birbirine zincirleme şekilde onlarca satır effect, side effect mantığı ile birbirine bağlanarak komplike yapılar oluşturulabilir ve bunlar uygulamayı yormadan, kullanıcıya data getir götür işlemlerini en az hissettirecek şekilde güncel veriler ile arka planda sessizce hallolur 🙂

Örnek bir Efekt kodu aşağıdaki gibidir;

@Effect()
websiteInfoPostRequestHandler = this.actions.pipe(
    ofType < websiteActions.WebsiteInfoPostRequest > (websiteActions.WEBSITE_ACTIONS.WEBSITE_INFO_POST_REQUEST_CMD),
    map(this.createWebsiteInfoReq()),
    switchMap(websiteInfoReq => {
        return this.websiteService.createWebsite(websiteInfoReq).pipe(
            map(response => {
                const websiteInformationPostRes = new WebsiteInfoResponseStateModel();
                if (response.success != null && websiteInfoReq.website != null) {
                    websiteInformationPostRes.isSuccessful = true;
                    websiteInformationPostRes.website = websiteInfoReq.website;
                    websiteInformationPostRes.website.WebSiteId = response.success.NewRecordId;
                }
                return websiteInformationPostRes;
            }),
            switchMap(result => {
                return this.getCustomerName(result);
            }),
            switchMap(lastResult => {
                if (lastResult.isSuccessful) {
                    return of(
                        new websiteActions.SetStoreWebsiteId(lastResult.website.WebSiteId),
                        new websiteActions.WebsiteInfoPostResponseReceived(lastResult)
                    );
                }
            })
        );
    })
);

Açıkcası NgRx ve NgRx Effects hakkında daha detaylı yazı yazmayı planlıyorum. Umarım mantığını kavramanız noktasında biraz açıklayıcı olabilmişimdir.

Happy Codings !

Tarih:NgRx

2 Yorum

    • kuthaygumus kuthaygumus

      Rica ederim, umarım faydalı olmuştur dostum 🙂

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir