Gece sıkılması, Redux kaynak kodundan öğrendiklerim
Redux gercekten hicbir sey yapmiyor.
Pazar gecesi yaklasik 2 saat Redux (opens in a new tab) kaynak kodu okuma maceramdan cikardigim sonuc bu oldu iste.
Yani bi'seyler yaptigi kesin, belki "yaptigi isi cok basit sekilde hallediyor" da denebilir
Her seyden once, Redux nedir?...
diye baslamayacagim tabi. Buraya kadar geldiyseniz Redux ne biliyorsunuzdur diye tahmin ediyorum.
Simdi
Bilginiz uzere reducer
dedigimiz fonksiyonlar state'i degistirir. Ve bunu
en yalin haliyle size yaptirir. Redux size onceki state'i ve bir action'i
verir. Siz de bu action'a gore yeni state'i dondurursunuz. Bu islemlerin hepsini
siz kendiniz yaparsiniz. Redux sadece uygulamanizdaki bazi yerlere "state degisti"
sinyalini gonderir. Peki nasil yapar bunu?
createStore
implementasyonuna (opens in a new tab) bu bakalim. Edge caseleri, type checkleri ve
typescript ile ilgili kisimlari gecip asil isleme bakarsak
ilgili kisim (opens in a new tab)
export default function createStore(reducer, preloadedState, enhancer) {
let currentReducer = reducer;
let currentState = preloadedState;
let listeners = [];
// ...
}
reducer
bildidigimiz gibi state'i degistiren fonksiyon. preloadedState
ise
uygulamanizin baslangic state'i. enhancer
zimbirtisi middleware
olaylarini sagliyor. Bu yazida onu ele almayacagim.
listeners
array'i dikkatimizi cekiyor. Vardir bir hikmeti deyip devam edelim
kodun ilerleyen kisimlarinda storun kendisini donduren bir getState
fonksiyonu
var.
ilgili kisim (opens in a new tab)
export default function createStore(/* ... */) {
// ...
function getState() {
return currentState;
}
// ...
}
O anki state'i almamiza yarayan bir fonksiyon. Guzel
kod subscribe
methodu ile devam ediyor
ilgili kisim (opens in a new tab)
export default function createStore(/* ... */) {
// ...
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
// ...
}
gorunuse gore bu fonksiyon listeners
array'ine bi'seyler ekliyor. Ve
unsubscribe
fonksiyonunu donduruyor. Bu fonksiyonu cagirdigimizda
listeners
array'inden listener'i cikariyor. Hmm, biraz garip bir islem
Vakit kaybetmeden devam ediyorum ki buyuk resmi gorelim. Asagida meshur
dispatch
fonksiyonu var
ilgili kisim (opens in a new tab)
export default function createStore(/* ... */) {
// ...
function dispatch(action) {
currentState = currentReducer(currentState, action);
listeners.forEach((listener) => listener());
return action;
}
// ...
}
Olayin koptugu yer burasi. dispatch
fonksiyonu bir action aliyor.
Bu action'i reducer
fonksiyonuna veriyor. reducer
fonksiyonu yeni state'i
donduruyor. Bu yeni state'i currentState
degiskenine atiyor. Ve listeners
array'indeki tum listenerlar cagiriliyor.
Buradan cikaracagimiz iki sonuc var. Ilk olarak dispatch
fonksiyonu reducer
i
kullanarak state'i degistiriyor ve yeni state olusuyor. Ikinci olarak listeners
array'i
icinde fonksiyonlar tutuluyor. Bu fonskiyonlarin hepsi dispatch
calistigi
anda cagiriliyorlar. Bu sayede "state degisti" sinyalini tum
listenerlara (subscribe olmus butun fonskiyonlara) gonderilmis oluyor. Bir onceki adimda
state, reducer
ile degistigi icin butun listenerlar yeni state ile calisiyor.
Son olarak gerekli olan degerleri ve fonskiyonlari createStore
fonksiyonu donduruyor.
ilgili kisim (opens in a new tab)
export default function createStore(/* ... */) {
// ...
dispatch({ type: '@@redux/INIT' });
return {
dispatch,
subscribe,
getState
};
}
Goruldugu gibi fonskiyon isini bitirmeden once bir dispatch
cagiriyor.
Bunun amaci reducer
fonksiyonu ilk calistiginda baslangic state'i dondurmek.
Boylece verilen reducer
a gore initial state olusmus oluyor. Burada action
type @@redux/INIT
olmasi onemli. Cunku reducer
fonksiyonu bu action
type'i goremezse baslangic state'i dondurmeli.
Tum kaynak kod sadelestirilmis hali ile su sekilde
export default function createStore(reducer, preloadedState, enhancer) {
let currentReducer = reducer;
let currentState = preloadedState;
let listeners = [];
function getState() {
return currentState;
}
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
function dispatch(action) {
currentState = currentReducer(currentState, action);
listeners.forEach((listener) => listener());
return action;
}
dispatch({ type: '@@redux/INIT' });
return {
dispatch,
subscribe,
getState
};
}
Bu kadar. Nasil calisitgina bakalim.
const counterReducer = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};
const store = createStore(counterReducer, 0);
store.subscribe(() => {
console.log('state changed', store.getState());
});
store.dispatch({ type: 'INCREMENT' });
// state changed 1
store.dispatch({ type: 'INCREMENT' });
// state changed 2
store.dispatch({ type: 'DECREMENT' });
// state changed 1
Kendin dene (opens in a new tab)
Evet bu kadardi. Redux'un kaynak kodu gercekten cok kisa ama suan NPM de haftalik indirme sayisi 8 milyon u gecmis durumda. React olmasa bu kadar populer olmazdi fakat isini guzel yapan bir kutuphane.
Ben de basit bir implementasyon yaptim Burada (opens in a new tab)
2024 © Faruk