redux
-
javascript icin bir state container aracidir. boyle tanimlayinca benim icin hicbir sey ifade etmiyor. daha iyi anlamak icin internette cesitli kaynaklara bakildiginda daha da kafa karistirici oluyor cunku "actions", "reducer", "store", "dispatch" derken farkli bir terminoloji ve bunun yaninda fonksiyonel programlama yaklasimi ile kafalar iyice karisiyor.
redux konusuna gelmeden once ogrenmek ile ilgili bir durumu aciklamak isterim. kucuklugumden beri bazi konulari anlamakta gucluk cektim, ve bu yuzden bazen geri zekali oldugumu dusundum. ama zaman icinde benim gibi bircok kisi oldugunun farkina vardim ve kendime en uygun ogrenme seklinin ne oldugunu kendimce kesfettim. ben bir konuyu oldugu gibi ogrenemiyordum, mutlaka ogrendigim sey bir neden sonuc iliskisi icinde bir yere oturmaliydi. bu olmadiginda kafam basmiyor, idrak edemiyorum.
redux konusu da bunlardan biri. ogrenirken terminoloji, kodlama gibi seyleri yapitorsun da kafamdan bir turlu "niye boyle yaziyoruz", "bu yazilan ne ise yariyor", "bunu yazmak zorunda miyiz" derken konsept bir turlu kafama oturmuyor.
bu durumun icinden cikmak icin internette arastirma yapmak da cogu zaman bir faydali olmuyor. cunku kaynaklarin cogu redux nedir tanimini yaptiktan sonra redux ile ilgili kod nasil yazilir ona odaklaniyor. benim aradigim cevap ise asil "nasil ?" degil "neden ?" sorusunun cevabi. "neden redux gerekli", "ne oldu da redux hayatimiza girdi", "neden reduxa ihtiyac duyuyoruz".
ıste bu yazida da onceden neredeydik, ve ne oldu da redux gibi bir teknolojiye ihtiyac oldu, bu surecte redux un react gibi frameworklerle iliskisi nedir anlatip daha sonra redux temel konseptini aciklayacagim. boylece ilk olarak "neden ?" sorusu cevabini bulacak, daha sonra "nasil ?" sorusunu aciklayacagim. tabi bunu anlatirken javascript nedir, dom nedir gibi temel konulari bildiginizi varsayiyorum.
bu aciklamada kullandigim orneklerdeki kaynak redux resmi sitesi, bu site de tek basina incelendiginde "nasil" sorusunun cevabini verirken "neden" sorusunun cevabi gecistirilmis diger bircok yerde oldugu gibi. simdi ilk sorudan baslayalim;
state container nedir?
bunu anlamak icin once bir web sitesi icin state nedir onu anlamak lazim. state bir web sitesinin o anki durumudur. onceleri web gelistirme alaninda boyle bir tabir pek kullanilmiyordu. cunku web sitesinin state yani durumu ayni zamanda mevcut dom ile ayniydi. sayfada gordugumuz her sey o anki durumu ifade ediyor yani state ve dom birbirinden ayrilmiyordu.
basit bir sekilde bu durumu soyle aciklayabilirim, ornegin sayfamizda bir buton dusunun. bu boton aktif yani enabled veya inaktif yani disabled durumda olabilir. daha onceleri bu butonun aktif mi ya da inaktif mi oldugunu bilmek ve ona gore islem yapmak icin o butonu dom uzerinde bulur, ve yine dom uzerinde o butonun attribute une bakar ve anlardik. yani butonun id, class, ve text, data gibi cesitli attributeler, hatta kendi belirledigimiz attributeler o butonu bulmak, ve o anki durumunu degistirmek icin kullaniliyordu.
tabi zamanla asenkron web siteleri ile birlikte bu dom yapilari cok daha karmasik hale gelmeye basladi, dolayisi ile her seyi dom uzerine yazmak ve oradan kontrol etmek uygulamayi cok karisik hale getirdi. bunun icin cesitli convention lar konulsa da bu karmasaya fayda etmedi. ornegin bazi class tanimlari o objenin renk, sekil, pozisyon gibi durumlarini belirlemek icin kullanilirken, bazi class tanimlari o objenin javascript tarafta temsilcisi oldular. zamanla dom uzerindeki her seyin bir sekilde javascript tarafinda bir kopyasi olusturulmak zorunda kalindi. ayrica bir butonun durumunda en kucuk degisiklik yapmak gerektiginde bu javascript objesi degistirildi, bunun uzerine bir de bir javascript fonksiyonu ile o butona ait dom objesi bulunmak, sonra uygun attribute bulunup, dom uzerinde de gerekli degisikli yapilmak zorunda kalindi. yani kisaca hem javascript uzerindeki state, hem de dom uzerindeki state bir sekilde senkronize edilmeli, tek bir olay icin iki farkli is yapilmak durumunda kalindi.
buna alternatif olarak react, angular, vue gibi frameworkler bize kolaylik sundular. bunlarin temelde yaptigi javascript objesi ile dom arasindaki senkronizasyonu saglamak, ayni zamanda da bize guvenilir bir yapi sunmak. butonun mevcut durumunu javascript tarafta degistirdigimizde dom uzerinde yapilacak gerekli isi, senkronizasyonu bu frameworkler yapiyorlar. yani artik javascript tarafta isbuttonenabled diye bir property tanimlayip onu basit bir sekilde enable veya disable yapip, daha sonra bunun sonuncunda dom a kadar gidecek olan zincirleme aksiyonu bu farmeworklere birakmis olduk. bunlar isin arkasinda gerekli olan render, veya bu render isleminin zamanlamasini, ya da neyin tekrardan render yapilip yapilmayacagini kontrol ediyorlar, bizim yerimize cozuyorlar.
ozetle sayfamizin o anki durumunu, hangi kutu acik, kullanici login oldu mu, oldu ise hangi kullanici, sayfada o anda goruntulenen veriler neler hepsini minimum buyuklukte bir javascript objesinde yani state de tutuluyor. minimum buyukluk diyorum cunku bu objede sadece degisken seyler tutuluyor. ornegin o butonun rengi sayfanin her yerinde ayni ise bu bir sabit oldugu icin state objesinde tutulmasi gerekmiyor. ozetle sayfada degisikenlik gosteren her sey bir state iken, degismeyen seyler state olarak tutulmuyor. ornegin bir butonun o an disable veya enable olup olmamasi bir state iken rengi, pozisyonu degismiyor ise state olarak tutulmuyor. state sayfamizin kucuk bir ozeti gibi birsey.
redux nedir, ne ise yarar ?
state degisikligi sonunda dom uzerinde yapilacak isler bu frameworklere devredildi ama artik state de buyudu ve karmasik hale geldi. iste bu durumda da state objesini yonetmek icin araclar cikti, bunlardan biri de redux.
redux daha cok react projelerinde kullanilsa da aslinda herhangi bir projede kullanilabilr. react ise bu state yonetim araci ile dom arasindaki baglantiyi kuruyor.
redux in asil kullanim motivasyonu state objesini minimum stateful sekilde fonksiyonel programlama paradigmasina gore, test edilebilir ve yan etkilerin minimize edilmesinden dolayi daha saglam bir yapi ortaya koymaktir.
redux bizim uygulamamamizin o anlik durumunu en kucuk hali ile tutan bir state makinasidir. yani redux da olasi tum olaylar yani actions tanimlaniyor, daha sonra bu aksiyonlarin gerceklesmesinin bizim state uzrinde ne gibi degisilik yaptigi tanimlaniyor reducers. state uzerinde yapilacak degisiklikleri belli kurallara bagliyor. bu reducerlar da dispatch diye ifade edilen tetikleyiciler ile calistiriliyor.
yani sayfadaki bir butonun enable yada disable olmasi gibi tum olaylar 'action', bir butonun enable ya da disable olmasini saglayan state objesi uzerindeki degisikligi yapan fonksiyonlar reducer, bu reducerlari tetikleyen emirler isedispatch.
actions nedir ?
sayfadaki tum olaylari tanimladigimiz javascript object
ornegin bir todo list dusun;
- yeni bir satir eklenebilir
- mevcut satir status toggle yapilabilir, yani completed | uncomplated gibi
- liste belli bir kritere gore filtrelenebilir.
bunlar bizim olasi aksiyonlarimiz.
nasildir bu action formati ?
basit bir js object
{
type: key_strıng,
payload
}
bu formatta type zorunluluk, unique string olmali.
payload olarak da istedigimizi tanimlayabiliriz.
ornegin yeni eklemek istedigimiz satir icin bu bir 'text' olabilir,
ya da toggle yapmak istedigimiz satir icin 'id' olabilir
ya da filter yapmak istedigimiz liste icin 'filter' olabilir.
action creator nedir?
actionlar tek basina kullanisli degildir. her bir action icin type ayni kalsa da payload hep degisir. ornegin toggle yapmak istedigimiz todo item icin id hep degisecektir. o nedenle actionlar dinamik olarak uretilmeli.
yani bir fonksiyon ile o fonksiyona bir payload gondermeliyiz, o fonksiyon da bize type hep sabit kalmakla beraber dinamik bir payload gondermeli.
addtodo = text => { type: 'add_todo', text};
toggletodo = id => { type: 'toggle_todo', id};
filtertodo = filter => { type: 'fılter_todo', filter};
yani ozetle action creator basit bir fonksiyon ve bize dinamik olarak action donuyor.
reducer nedir?
reducer ismi array.reduce dan geliyor. bu fonksiyona gonderdigimiz higher order fonksiyona da reducer deniliyor.
ne yapiyor bu reducer? array icindek her bir elemani teker teker bu reducer fonksiyonu cagiriyor, ama cagirirken hem bir onceki reducer fonksiyonunun gonderdigi elemeani hem de mevcut elemani gonderiyor. ornegin;
const arr = [1,2,3,4];
arr.reduce( (accumulator, value) => {
// artik burada ne yaparsan
// ornegin bir onceki deger ile bir simdikini toplarsan
return accumulator + value;
// return degeri bir sonraki reducer fonksiyonuna accumulator olarak gider
});
redux daki reducer da benzer sey yapiyor. onceki state ve aksiyonu aliyor, ve bundan yeni bir state olusturup donuyor.
bu sekilde bir state sahibi olalim;
{
filter: 'foo',
todos: [
{
text: 'bar',
completed: false
}
]
}
yani reducer bir pure function, state manipulasyon icin kullaniliyor.
function todoapp (state = initialstate, action){
switch(action.type) {
case add_todo:
case toggle_todo:
case fılter_todo:
default:
return state;
}
}
tabi reducer ilk calistiginda accumulator yani redux da state undefined olarak geliyor. dolayisi ile ilk reducer calistiginda bir initial state donmek gerkiyor ki bu initial state bir sonraki reducerda mevcut state olsun.
reducer ile ilgili en onemli konu reducerlar pure function olmali. yani asla icinde bir state barindirmamali, asla `math.random()veyadate.now()` gibi fonksiyonlar kullanilmamali. ve cok onemli kendisine gelen state objesini asla degistirmemeli, yeni bir obje yaratip donmeli.
function todoapp (state = initialstate, action){
switch(action.type) {
case add_todo:
return object.assign({}, state, {
todos: [...state.todos, { text: action.text, completed: false}]
});
case toggle_todo:
// find item and change and assign new object
case fılter_todo:
return object.assign({}, state, { visibilityfilter: action.filter});
default:
return state;
}
}
store nedir ?
store tum bu elementleri bir araya getirmek icin kullanilir ve her bir redux uygulamasi sadece bir store sahibi olur. store olusturmak icin createstore fonksiyonu cagirilmalidir, ve bu fonksiyon main reducer objesini parametere olarak alir. ayrica ekstradan bir de init state de store a gonderilebilir.
import { createstore } from 'redux'
import todoapp from './reducers'
const store = createstore(todoapp)
ayira state store yaratirken initia state de tanimlayabilirs;
const store = createstore(todoapp, window.state_from_server)
dispatch nedir?
simdi elimizde store, store icine gonderilmis reducer, reducerlarda kullanilmak uzere action var. artik actionlar tetiklenmeli, dolayisi ile o actiona uygun reducer calismali ve state degismeli. bunin icin dispatch kullaniliyor.
import {
addtodo,
toggletodo,
setvisibilityfilter,
visibilityfilters
} from './actions'
// log the initial state
console.log(store.getstate())
// dispatch some actions
store.dispatch(addtodo('learn about actions'))
store.dispatch(addtodo('learn about reducers'))
store.dispatch(addtodo('learn about store'))
store.dispatch(toggletodo(0))
store.dispatch(toggletodo(1))
store.dispatch(setvisibilityfilter(visibilityfilters.show_completed))
bu ornekte actionlar import ediliyor, ayni actionlar reducerda da kullaniyor. yani reducer ve dispatch aksiyonun arasindaki baglanti bu action tanimlamalari yani action.type. cunku dispatch da belirttigimiz action, reducer icinde kullanilan switch tarafindan kontrol edilip ona gore uygun reducer fonksiyon calisiyor.
subscribe nedir?
bir state degistiginde o state degisikligini dinlemek yani state degistiginde bir fonksiyon cagirilsin istersek o store icin subscribe yapiyoruz.
const unsubscribe = store.subscribe(() => console.log(store.getstate()))
subscribe fonksiyonu bir unsubscribe fonksiyonu donuyor ve bu fonksioynu kullanarak da unsubscribe yapabiliriz.
unscubscribe();
basta da dedigim gibi burada kullanidigim ornekler redux resmi sitesinden alinda, ama ben ek olarak "nasil" sorusunun yaninda "neden" sorusunu da aciklamaya calisttim. -
bir hastalik, emeklilik yada uzun suren ayriliktan sonra geri donmek anlamina gelen ingilizce kelime.
-
insanların anlaması çok zor dediğine bakmayın, bir kere öğrendiğinizde react native gibi yaygın kullanılan bi frameworkde çok rahat uygulama geliştirebilirsiniz. mantığını biraz anlatmaya çalışayım müsadenizle.
şimdi diyor ki bu arkadaş, eğer user interface'in üzerindeki işlemleri actiona bağlarsan, ne zaman kullanıcı bu ekran üzerinde ilgili bir işlem yaparsa, actiondaki karşılık gelen işlemi tetiklerim, actiondaki dönen sonucu da ilgili reducera gönderirim diyor. reducer'da state'deki veriyi güncelliyor. bu işlem sonucunda güncellenen state propertylerini içeren bütün user interfaceler re-render oluyor.
bi örnek ile biraz daha kafanızda canlandırmaya çalışayım. şimdi diyelim ki ekranınızda bir + işlemi var, bir de 1 değerini tutan state'in counter property'si var. ne zaman siz bu + işaretine basarsanız, ekrandaki sayının 1 artmasını istiyosunuz. bu işlemi gerçekleştirmek için bu + butonunun press eventine actionda bir metod bağlıyosunuz. kullanıcı + ya bastığı zaman bu metod mevcut sayıyı alıp üzerine 1 ekleme işlemini yapıyor. dönen sonucu da reducer'a gönderiyor. reducer state deki counter property'sini update ediyor. ardından bu state'in counter property'sini içeren ekran yeniden render oluyor ve ekran 2 olarak güncellenmiş oluyor.
yani işlem sırası:
ui event > action > reducer > re-render şeklinde.
dikkat etmeniz önemli nokta reducer her zaman bir sonuç dönmek zorunda. yoksa işleminiz error verir.
eğer bu yazdıklarım anlaşıldıysa ve talep olursa dispatch mantığını da basitçe ekleyebilirim.
edit: dispatch mantığını da kısaca ekleyim. şimdi biliyosunuz kodumuz asenkron çalışıyo. yani bi task çalışırken yerine göre paralelde başka bi task da çalışabiliyo. örnek veriyorum, databaseden bi veri almak istediniz, bunu da action'da get( ) methodunun içinde yaptınız diyelim. gönderdiniz requesti, datanın dönmesini bekliyosunuz. siz kodun içerisinde başka işlemler yaparken, asenkron çalışan get( ) methodu 5 saniye sonra sonuç döndü diyelim. işte bu returnü yani dönen sonucu dispatch( )'in içine koyarsanız, dispatch sonuç döndüğü anda sonucu reducera aktarıyo. gerisi yine aynı redux mantığı. reducer state'i güncelliyo. o state'i içeren ekranlardaki componentlar da rendee oluyo. böylelikle asenkron çalışan methodlarınızı handle etmiş yani halletmiş oluyosunuz. -
diyelim ki youtube'tasin, youtube ta sag'da video list var
o video list'teki her bir elemana da videoelemani de
orta'da videoplayer'in olsun
react'ta ne yapiyorsun videoplayer'a secilen video'yu yuklemek icin?
1. render: videolist wrapper'i, icine her bir videoelemani, ortaya'da videoplayer component'i.
2. props: videolist'in propslarini, videoelemanina gonderiyorsun
3. peki ya videoelemanina tiklaninca videoplayer'in calismasi icin ne yapiyorsun?
videolist'te bir eventhandler yaratip, onu videoelemanina gondermiyor musun? boylelikle videoelemanindaki olay, state'i update etsin. state'in ne oldugunu bildigini varsayiyorum.
sonra eger ki farkli fonksiyonlar eklersen atiyorum, kac kere tiklanmis, sevilmis mi yoksa oeh bu ne lan mi demis vs. vs. bunlar icin de ayri eventhandler ve state yazman gerekmiyor mu?
redux diyor ki,
aga: senin statelerin hepsini ben storage'ta tutucam. storage farz etki key/value esleri olan buyukce bir object listesi, hersey bu storage'ta olacak, butun componentler bu storage'tan bilgiyi alacak. tek merkezli calisicaz.
olayi component'ten baslatiyor, diyor ki aha video'ya tikladi yada arama butonuna yazmaya basladi...
gidiyor, action yaratiyor,
action dedigin tekil key/value object ornegin
{
type: "vıdeo_clıcked"
payload: videoıd
}
bu type gidiyor, reducer denilen zamazingoya iletiliyor
reducer aliyor bu object'i okuyor:
ister switch ile yaz, ister bir suru if/else ile yaz okudug action sonucunda gidip
storage'i guncelliyor,
storage: guncellemesi
reducer storage'a diyor ki, aga hani calan video ıd'si eskiden oydu ya, aha bizim kullanci simdi bu video id'sini istiyor, bunu yukle
storage bunu guncelliyor, sonra provider'a gonderiyor...
provider'in tek ozelligi, eskiden react ile yazdigin state/eventhandler/render vs. gibi sikkolari ortadan kaldiyor, boylelike state'ini storage' a veriyorsun, eventhandler'larin da en son component'in kendisinde kaliyor, boylelike eventdrill ortadan kalkiyor.
provider'in yaptigi tek sey, root/app vs. artik adini ne koyduysan, yaptigin app'i wrap ediyor, boylelikle react-redux birlikte calismaya basliyor
sonunda, provider'in app'ine bilgiyi gonderiyor, bu bilgi de iliskili component'in container'ina gidiyor.
container'in da tek yaptigi sey storage' bilgisine ihtiyaci var mi? component'in action'i fire etmesi gerekiyor mu, hepsi bu.
he arada async request icin thunk var, onu da baska zamana anlatirim -
mulder'a en buyuk yalanin bir parcasi oldugunu soyleyen michael kritschgau'nun asmis monologu sayesinde amerikan komplo tarihini 3 dakikaya sigdirmis efsanevi the x files bolumu.
kritschgau: level 4 is a biological quarantine wing. it houses a series of labs and medical facilities, and an elaborate facility for the storage of mass quantities of dna.
mulder: dna from whom?
kritschgau: virtually every american born since 1945. every immigrant, every indigenous person who's ever given blood or tissue to a government donor. this is what i was telling you. this is the hoax into which you've been drawn. the roots go back 50 years to the end of world war ii. playing on a virulent national appetite for bogus revelation and a public newly fearful of the atomic bomb... the u.s. military command began to fan the flames of what were being called flying saucer stories. there are truths that can kill a nation, agent mulder. the military needed something to deflect attention away from its arms strategy - global domination from the capability of total enemy annihilation. the nuclear card was fine as long as we alone could play it. but the generals and politicos knew they could not win a public relations war. those photographs from nagasaki and hiroshima were not faces americans wanted to see in the mirror. oppenheimer knew it, of course, but we silenced him. when the russians developed the bomb, the fear in the military was not for safety at home, but for armistice and treaty. the business of america isn't business, agent mulder, it's war. since antitam, nothing has driven the economy faster. we needed a reason to keep spending money, and when there wasn't a war to justify it, we called it a war anyway. the cold war was essentially a fifty year public relations battle... a pitched game of chicken against an enemy we not much more than called names. the communists called us a few names, too. "we will bury you," kruschev said, and the public believed it. and after what mccarthy had done, they ate it with a big spoon. we faced off a few times in cuba, korea, vietnam, but nobody dropped the bomb - nobody dared.
mulder: but what does all this have to do with flying saucers?
kritschgau: the u.s. military saw a good thing in '47 when the roswell story broke. the more we denied it, the more people thought it was true - aliens had landed. a made-to-order cover story for generals looking to develop the national war chest. they opened official investigations with names like grudge, twinkle, project blue book, majestic 12. they brought in college professors and congressmen and fed them enough bogus facts and fuzzy pictures and eyewitness accounts that they believed it, too. they even hooked doug macarthur, for god's sake. i can't tell you how fortuitous it was. do you know when the first supersonic flight was, agent mulder? 1947. soon every experimental aircraft being flown was a ufo sighting. when the abduction stories started up, it was too perfect. we almost got caught in korea, an ambitious misstep. china and the soviets knew it. the un got all heated up at us.
mulder: germ warfare. we were accused of using it in the korea.
kritschgau: it was developmental then, nothing like what we and the russians have now. the bio-weapons used in the gulf war were so ingenious as to be almost undetectable. developed in this very building.
mulder: what about all the reports of abductions? you're saying they've all been lies?
kritschgau: not lies exactly, but citizens taken unsuspecting and tested. a classified military project, above top-secret and still ongoing. you've heard the recent denials about roswell by the military and the cia. what's been the effect? even wilder and more widespread belief. the american appetite for bogus revelation, agent mulder. -
şurada dilimin döndüğünce anlatmaya çalıştım: https://medium.com/…u-kaçırmamak-redux-8d822da0d19b
-
yazılım geliştiriciyim. ne öğrendiysem otodidaktik yöntemle başardım. hani öğretmen derdi ya "kimisi bir kerede anlar kimisi 5 kerede" falan diye. işte ben hep o bir kerede anlayanlardan oldum.
ama redux'ı özümseyemedim lan. hep kusursuz çalışan anlama, öğrenme yöntemim işe yaramadı. ya hep bahsedilen bir yaştan sonra kafanın yavaşlaması durumunu yaşıyorum ya da bu redux'ta bir saçmalık var.
bu entry redux ele alınınca silinecektir. -
react gibi js library/framework'lerle büyük ölçekli bir app geliştirecekseniz kullanmanız gereken bir state holder.
özellikle component based frameworklerde iç içe kullanılan componentlerin birbirlerine state aktarması bir noktadan sonra karmaşaya yol açıyor. bu eklenti ile bütün componentlerin verileri tek bir state'e gönderip yine oradan okumasını sağlayabilirsiniz.
http://redux.js.org/ -
js libinden bahsediyorum.
eğer basitleştirme dediğiniz buysa abi biz pılı pırtıyı toplayıp gidelim.
yazılım bu değil lan, valla değil bak...
30 objeyi birbirinin altına sokuşturunca valla tasarım olmuyor.
sizin çözüm diye sunduğunuz yaklaşımı mikiyim. siz yazılımı da basitleştirmeyi de sürdürülebilirliği de yanlış anlamışsınız.
js dünyası boka sarıyor ama dur bakalım.
bi ara akıllının biri çıkıp biz ne bok yemişiz, abi bunlar ne diyecek. de biz gebermiş olacağız. -
kendisini kullanmayı biliyorsanız ancak nasıl çalıştığını adım adım öğrenmek yada daha rahat kullanmak istiyorsanız freecodecamp redux kursunu tavsiye ederim. sıfırdan öğrenmeye çalışan biri bence anlamakta güçlük çeker ama iyi-kötü kullanabilen biri mantığı bu kurs ile öğrenebilir.
ekşi sözlük kullanıcılarıyla mesajlaşmak ve yazdıkları entry'leri
takip etmek için giriş yapmalısın.
hesabın var mı? giriş yap