Redux Nedir? React’ta Redux Nasıl Kullanılır?

Duygu Evrim Odabaş
6 min readMar 4, 2021

--

Herkese Merhaba :) Bu gönderide Redux’ın ne olduğundan kısaca bahsettikten sonra neden kullandığımızdan, React ile nasıl kullanıldığından ve temel kavramlarından bahsedeceğim.

Redux

Javascript uygulamalarında state yönetimini sağlayan bir JavaScript kütüphanesidir. State kavramı hakkında bilgi sahibi değilseniz, state ile ilgili yazıma linke tıklayarak ulaşabilirsiniz. React ile geliştirdiğiniz bir projede component’ler içerisinde genellikle state’ler kullanılmaktadır ve component’lerinizin sayısı arttıkça state’lerinizin sayısı da artar. Bu durumda, geniş kapsamlı uygulamalarda state’leri yönetmek gittikçe zorlaşır. Redux size state yönetimi konusunda yardımcı olarak oluşan bu zorluktan kurtulmanızı sağlar. Redux hakkında bahsedeceğim kavramların listesi aşağıdaki gibidir.

Store Kavramı
Redux Data Flow
Subscribe Metodu
CombineReducers Kullanımı
Provider Kavramı
Connect
mapStateToProps
mapDispatchToProps
mergeProps
Redux Thunk Middleware
Redux Logger Middleware
Immutable vs Mutable

Store Kavramı

Redux kütüphanesi ile beraber yaratacağınız verilerin tutulacağı alandır. Store bir sınıf değildir. Üzerinde birkaç method bulunan bir nesnesidir. Uygulama içerisinde tek bir store’umuz vardır. Redux 6 ile birlikte çoklu store desteği gelmiştir. Ancak çok kompleks uygulamalar dışında kullanılması tavsiye edilmemektedir.

Oluşturulan state’ler, store içerisinde depolanır ve yönetilir. Component’ler de oluşan bu store’a abone durumdadırlar. Store üzerinde herhangi bir değişiklik olduğu zaman componentler notify olur ve kendilerine ait ilgili güncellemeyi yaparak ui re-render edilir.

Store nesnesinde aşağıdaki üç method bulunur.

  • store.getState() : state nesnesini verir.
  • store.dispatch() : state’i güncellemesi için reducer'a action gönderir.
  • store.subscribe() : store'da oluşan güncellemeleri dinler.

Redux Data Flow

Redux Data Flow

Bu kısımda, yukarıdaki flow üzerinden Redux’un çalışma mantığını açıklamaya çalışacağım.

View: Kullanıcının web sayfasında karşılaştığı ekrandır.

Action: Sayfada bir input alanı olduğunu ve bu input alanındaki verileri aktarmak için bir buton olduğunu varsayalım. Input alanına veri girip butona basıldığı zaman bir action gerçekleşmiş oluyor.

Dispatch: Input’a yazılmış olan değeri store’a dispacth etmeniz gerekiyor. Burada bahsedilen dispatch kavramı, action üzerindeki veriyi store’a gönderme işine yaramaktadır.

Reducer: Yukarıdaki işlemler gerçekleştikten sonra data artık reducer’lardadır. Reducer’lar, gelen action bilgisine göre uygulamanın state’ini istenilen şekilde günceller ve tekrar store’a gönderir. Reducer’ları, alınan action tipine göre event’leri işleyen bir event listener olarak düşünebilirsiniz.

Reducer’ların yaptığı veri güncelleme işleminden sonra, store üzerinde yapılan bu değişiklik View’a yansır ve döngü tamamlanmış olur.

Reducer’ların aşağıdaki kurallara uygun olması gerekir.

  • Yeni state değerini yalnızca state ve action parametrelerine göre hesaplamaları gerekir.
  • Var olan state’i değiştirmelerine izin verilmez. Bunun yerine, var olan state’i kopyalayarak, kopyalanan değerleri değiştirip immutable güncellemeler yapmaları gerekir.
  • Side effect (yan etki) barındıran işlemler içermemelidir.

Örnek Kullanım

İlk olarak gerekli paketleri projemize dahil etmeliyiz. Aşağıdaki komut yardımı ile redux ve react-redux paketlerini kolayca ekleyebiliriz.

npm install redux react-redux --save

Store Oluşturma

Öncelikle store oluşturabilmeniz için createStore nesnesini projeye dahil etmeniz gerekiyor. Bu işlem için redux paketini kullanıyoruz. Aşağıdaki şekilde index.js dosyasına import edebiliriz.

import { createStore } from 'redux';

createStore’u uygulamaya dahil ettikten sonra bir reducer yaratmanız gerekir. Yaratılan reducer, store nesnesine parametre olarak verilerek store’a bağlanır. Aşağıdaki kod parçası çalıştığı zaman getState() fonksiyonu sayesinde reducer’dan dönen “state” değeri console’a basılır.

Store Güncelleme

Bu aşamada var olan reducer’a action ile müdahale ederek store içindeki state’leri action’dan gelen payload ile güncelleyeceğiz. Store güncellemek için dispatch() metodu kullanılır.

Öncelikle action oluşturulur. Action’un tipi belirtilir ve ilgili data payload özelliği altında gönderilir. Daha sonra action, store’a dispatch edilir.

Yukarıdaki kodda, gönderilen action tipi “update” ise state’in yeni değerini return etmesini söylemiş oluyoruz. Eğer böyle bir ifade yoksa default olarak state‘i return edecektir. Yukarıdaki kod parçasında ilk olarak “state” yazısı basılır ve daha sonra store güncellenince “Redux öğreniyoruz” yazısı konsol’a basılır. Konsol çıktısı aşağıdaki gibidir.

Örnekten de anlaşıldığı gibi reducer’lar store’da bulunan state’i alıp, bizim vermiş olduğumuz payload’daki data ile güncelleyerek yeni datayı geri döner ve store’u güncellemiş olur.

Subscribe Metodu

Store da yapılan herhangi bir değişiklikten haberdar olmak istediğimiz zaman, component’ler subscribe metodu ile store’a subscribe (abone) olur. Store’a subscribe olan tüm componentler store içerisinde saklanır.

CombineReducers Kullanımı

Gerçek hayattaki uygulamalarımızda genellikle birden çok reducer kullanacağımız için bu reducer’ları CombineReducers metodu ile birleştirebiliriz. Redux bizim için bu reducer’ları ortak bir objede tutarak erişimi ve kullanımı kolay bir hale getirir. Ortaya çıkan reducer, her child reducer’ı çağırır ve sonuçlarını tek bir state nesnesinde toplar.

Aşağıdaki kod parçasında blogReducer ve authorReducer olarak iki ayrı reducer’ımız var. Bu reducer’lar combineReducers fonksiyonu ile birleştirilerek createStore nesnesine verilir ve store’a bağlanır.

Klasörleme : Reducer’larınızı yukarıda olduğu gibi index.js içerisinde oluşturup store’a bağlayabilirsiniz. Ancak ayrı ayrı klasörlediğiniz zaman daha temiz ve anlaşılır bir kod yazmış olursunuz. Aşağıdaki gibi actions ve reducers isimli iki ayrı klasör oluşturarak geliştirmenize devam edebilirsiniz.

Author için örnek action ve reducer kaynak kodu aşağıdaki gibidir.

Provider Kavramı

Redux store’unuzun React uygulamanız içerisinde erişilebilir ve kullanılabilir olması için provider isimli nesne ile sarmalamanız gerekiyor. Bu işlemi gerçekleştirmek için react-redux modülünün içerisinde bulunan Provider nesnesini rojeye dahil etmelisiniz. Provider ile sarmalama işlemi gerçekleştirilirken store isimli bir parametre tanımlanır. Bu parametreye oluşturmuş oluşturmuş olduğunuz store nesnesinin ismini yazarak sarmalama işlemini gerçekleştirebilirsiniz. İşleme ait kod parçası aşağıdaki gibidir.

Connect

Bu kısma kadar store oluşturmayı, güncellemeyi ve React uygulamamız içerisinden erişilebilir kılmayı öğrendik. Şimdi de oluşturmuş olduğumuz store’u componentimize bağlamak için connect isimli nesneyi kullanmamız gerekiyor.

Yukarıdaki kod parçasında ilk olarak react-redux modülü içerisindeki connect nesnesini component’lerimizin bulunduğu sayfaya dahil ediyoruz. Daha sonra component’imizi oluşturuyoruz ve bu component’i export ederken oluşturduğumuz component ismini ikinci parantezin içerisinde parametre olarak belirtmemiz gerekiyor. İlk parantezin içerisine mapStateToProps ile map’lenen state verilir. mapStateToProps sayesinde o anda state içerisinde bulunan bilgi component içerisinde props olarak kullanılabilir olur.

📌 Yukarıdaki kod parçasında mapStateToProps’a tüm state’i verdik. İlgili component içerisinde tüm state’e ihtiyaç duymayabilirsiniz. Örneğin blog ve authors isimli iki state’e sahip olduğumuzu varsayalım ve bu tanımlanan component’te sadece author state’i kullanılıyor olsun. Bu durumda mapStateToProps tanımının aşağıdaki gibi sadece author bilgisi kapsayacak şekilde yapılması daha mantıklı olurdu.

mapDispatchToProps

connect’e ikinci parametre olarak verdiğimiz ve dispatch ettiğimiz action’ları map’leyen bir yapıdır. Her seferinde dispatch kullanmak yerine mapDispatchToProps sayesinde bu işlem gerçekleştirilebilir.

mapDispatchToProps kullanarak veri güncelleme işlemine ait tüm kaynak kodlar aşağıdaki gibidir.

mergeProps

Connect’e üçüncü bir parametre olarak verilebilir. Hangi props’un nereden geldiğini görmemize yardımcı olur. Aşağıdaki gibi kullanılabilir.

Görüldüğü üzere mergeProps üç adet parametre almaktadır.

  • propsFormState, state’den gelen propsları
  • propsFormDispatch, dispatch’den gelen propsları
  • ownProps, componentlere kendi verdiğimiz propsları ifade eder.

mergeProps içerisinde boş da olsa bir geri dönüş değeri bulundurmalıdır.

Redux Thunk Middleware

Middleware, asıl yapılmak istenen işten önce, işlemi farklı işlemlere tabi tutup, ortaya çıkan sonuca göre en son işleme geçmeyi sağlayan ara katmandır. Redux’ta reducer’ların pure (saf) olması gerekmektedir. Ancak API istekleri gibi işlemlerde pure olmayan işlemler yapılması gerekir. Bu noktada middleware kullanılması gerekir. redux-thunk middleware kütüphanesi, Reducer’ların pure halde kalmasını sağlar. Kurulumu aşağıdaki gibi yapılır.

npm install redux-thunk --save

Middleware eklemek için redux’ın applyMiddleware fonksiyonundan yararlanılır. createStore fonksiyonunun ikinci parametresine bu fonksiyonu göndererek middleware’leri aktif hale getirebiliriz.

Redux Logger Middleware

Önceki state’inizi, action değerinizi ve action sonucunda oluşan mevcut state’inizi console’a basan bir middleware’dir. redux-logger paketini projenize dahil ederek kullanmaya başlayabilirsiniz.

Immutable vs Mutable

JavaScript programlama dilinde value types ve reference types olmak üzere iki adet veri tipi mevcuttur.

JavaScript’te objeler ve arrayler referans tipli veri tipleridir ve mutable yapıdadırlar. Değişkenin değerinde herhangi bir değişiklik yapıldığı zaman Ram’deki referans adresleri değişir. Bu durumdan kaynaklı olarak da aynı referans adresine eşitlenen diğer değişkenin de değeri güncellenir.

Aşağıdaki örnek sayesinde bu durum daha net anlaşılabilir.

Yukarıdaki konsol çıktısında count state değeri en son 4'e eşitlendiği için her yerde 4 olarak gözüküyor. Referansın işaret ettiği bellekteki kısım değiştirilmiş oldu. Bunun sonucunda da tüm count çıktıları aynı referansı kullandıkları için değer hepsinde aynı gözükür.

Store’u update etmek istediğinizde, bir önceki state değerinin üzerine ilgili değişiklikler yazılarak return edilmelidir. Böylelikle kullanıcının geriye dönük yaptığı işlemleri görebiliriz.

Bu durumdan kurtulmak için state’iniz aşağıdaki gibi immutable yapıya getirmeniz gerekir. Yukarıda kullandığımız “state.count += action.payload;” eşitlemesi yerine ES6'daki spread operatörünü (…) kullanarak state’inizde o anda hangi değer varsa alabilirsiniz. Daha sonra değiştirmek istediğiniz değeri aşağıdaki gibi verebilirsiniz.

Şimdilik anlatacaklarım bu kadar :)
Zaman ayırdığınız için teşekkürler. Umarım faydalı olmuştur🙂

--

--