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 1Kendin 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