Sıfırdan İleriye ReactJs serisinin yeni konusuna hoş geldiniz. Bugün React için oluşturulmuş ve çokça kullanılan bir özellik olan Redux Toolkit öğreneceğiz. İyi okumalar.
Redux Toolkit Nedir ?
Bazen uygulama yaparken kullandığımız stateleri yani useState bunları bir compenent'den başka bir compenent'e aktarmak isteyebiliriz. Bunun için hep props kullanmak durumunda kalırız. Hatta bir child-parent mantığıyla kullanacağınız child ne kadar aşağıda ise her seferinde o child'in parent'ine props almak zorunda kalacağız. Bu büyük projelerde 10-15 tane props oluşturmak anlamına gelir. Hem performans açısından hem zaman açısından pek olumlu bir şey değil. İşte bu gibi durumlarda Redux Toolkit kullanarak stateleri bir dosyada depolayıp istediğimiz zaman istediğimiz dosyaya o stateleri alabilme imkanı veriyor.
Kısaca Redux Toolkit ile tüm compenentleri saran bir yapı oluşturur ve compenentlerdeki state ve fonksiyonları Redux Toolkit'e aktarıp istediğimiz zaman bu fonksiyon ve stateleri çekebilir ve kullanabiliriz.
Bir de Redux vardır. Redux, Redux Toolkit'in eski halidir diyebiliriz 2015-2018 zamanlarında kullanılıyordu ama eskidi ve yerini Redux Toolkit'e bıraktı. Aşağıdaki gif dediklerimi özetler şekilde birkaç dakika bu gif'i inceleyin. Daha sonra Redux Toolkit'e girişimizi yapalım.
Redux Toolkit Kurulum ve Kullanımı
Redux Toolkit'i önce terminal üzerinden kurmamız gerekiyor. Bunun için aşağıdaki kodu yazmanız yeterli olacaktır.
Kod:
npm install @reduxjs/toolkit
Terminale kurduktan sonra bir store dosyası oluşturmamız lazım. Bu store dosyasının içine dokümantasyonda yazan kodları yazacağız.
JavaScript:
import { configureStore } from '@reduxjs/toolkit
export const store = configureStore({
reducer : {
},
})'
İndirdiğimiz reduxtan configureStore değişkenini dosyaya import ediyoruz ve oluşturulan store değerini export ederek diğer sayfalara import edebilmeyi aktif hale getirdik. Bu direkt zorunlu bir şey herhangi bir mantık beklemeyin burada şimdilik. Şimdi main dosyamıza gelip şunları yazalım.
Kod:
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { store } from './Redux/store.jsx'
import { Provider } from 'react-redux'
createRoot(document.getElementById('root')).render(
<Provider store={store}>
<App />
</Provider>
)
Buradaki mantık App compenentini Reduxtan aldığımız özellik olan Provider ile sarıyoruz ve Provider'in store değerini az önce oluşturduğumuz store dosyasını tanımlıyoruz. Bir veri alacakken bu store üzerinden alacağız. App compenenti bizim ana sayfamız. İşte tüm verileri ana sayfadan çekmemize yardımcı olacak.
Şimdi bir adet de slice oluşturmamız lazım. Bunun için bir dosya daha oluşturalım.
Kod:
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
}
export const slicer = createSlice({
name: 'slicer',
initialState,
reducers: {}
})
export const { } = slicer.actions
export default slicer.reducer
Slicer dediğimiz şey temelde böyle. Yapacağımız işlemlere göre bu yerler dolacak. Şimdi ilk olarak Redux'tan createSlice özelliğini import ettik ve initialState diye bir yapı oluşturduk. Daha sonra bir slicer oluşturup bunu createSlice formatında olacağını belirttik ve ad, initialState ve reducers ( fonksiyonları burada oluşturacağız.) tanımladık. slicer.actions ile oluşturacağımız fonksiyonları kullanıma açtık şimdilik boş ama fonksiyon yazıldıkça göreceksiniz. Son olarak reducerleri kullanıma açtık.
Az önceki store dosyasına gelip bu oluşturduğumuz slicer'i import edelim.
Kod:
import { configureStore } from '@reduxjs/toolkit'
import Slicer from './Slicer'
export const store = configureStore({
reducer: {
slice: Slicer
},
})
Son olarak da bu Redux'u kullanacağımız dosyaya selector ve dispatch hooksları import ediyoruz. Import edilen özellikleri bir değişkene atıyoruz selector ile store içinde bulunan slice özelliklerini alıyoruz. En son olarak da konsola yazdırdım ama bir şey çıkmayacak çünkü slice değeri boş.
Kod:
import { useSelector } from 'react-redux'
function App() {
const state = useSelector((store) => store.slice)
console.log(state)
return (
<div>App</div>
)
}
export default App
Buraya kadar her şey anlamsız geldi ise merak etmeyin. Burada kullanımı öğrenmeniz önemli çünkü Redux Toolkit yapanlar böyle hazır bir sistem oluşturmuş hiç karıştırmaya gerek yok kullanımını öğrenmeniz yetecektir. Şimdi slice içini dolduralım biraz daha iyi anlayacaksınızdır.
Slicer içindeki initialState kısmı bir nevi değişken değeri saklama yeridir. Buraya atanan değerleri uygulamanın her yerinden rahatça erişebilirsiniz. Ben bir adet "değer" değişkeni tanımlayıp 1 sayısını veriyorum.
Tamam burada değeri saklıyoruz peki fonksiyonlar ?
Fonksiyonları ise reducers içlerine tanımlarız. Ek olarak eğer api çekme gibi asenkron işlemler için ise extraReducers oluştururuz bu konuyu ileride göreceğiz şimdilik ismen bilin yeter. Şimdi reducers içine iki adet fonksiyon tanımlayacağım biri sayıyı arttırırken diğeri sayıyı azaltacak.
JavaScript:
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
deger: 1
}
export const slicer = createSlice({
name: 'counter',
initialState,
reducers: {
arttir: (parametre) => {
parametre.deger +=1;
},
azalt: (parametre) => {
parametre.deger -=1;
}
}
})
export const { arttir, azalt } = slicer.actions
export default slicer.reducer
Fonksiyonlar içine genelde state yazılır. State.deger gibi işlemler yapılır ama ben o parametre kısmına istediğiniz şeyi yazabileceğimizi göstermek adına parametre olarak yazdım. Tamam fonksiyonlarımız var ve parametresi var. Parametre içindeki değer değişkenin içindeki değeri al bir ekle veya çıkar diyorum. Son olarak da bu oluşturduğum fonksiyonları export yani diğer componentlere kullanımı açıyorum direkt import edip kullanabileceğiz bu şekilde. (Resimde = konulmamış işlemlere bu şekilde değer artmaz/azalmaz. İşlemde "=" koymayı unutmayın)
JavaScript:
import { useSelector } from 'react-redux';
function App() {
const { deger } = useSelector((store) => store.slice);
console.log(deger);
return (
<div>
<div>{deger}</div>
<div>
<button>Arttır</button>
<button>Azalt</button>
</div>
</div>
)
}
export default App;
Burada useSelector ile değerimizi önce store gidip senin içinde slice varmış onun içinde initialState varmış onun içinde deger diye bir değişkenin değerini almam gerektiğini söylendi bana diyip slicer içindeki değişken değerini aldık. Konsola basarsak ve ekrana yazdırırsak slicer içinde tanımladığım değer göreceğiz.
Daha sonra bu değeri ekrana yazdırdık ve iki tane buton koyduk. Şimdi değer almayı gördük oluşturduğumuz fonksiyonlar vardı şimdi onları useDispacth ile alacağız. Bunun için dispatch'i import etmeniz lazım gözden kaçırmayın bunu.
JavaScript:
const dispatch = useDispatch();
Şimdi dispatch ile fonksiyonları alacağız.
<button onClick={() => { dispatch(arttir) }}>Arttır</button>
<button onClick={() => { dispatch(azalt) }}>Azalt</button>
Bu butonlara basınca arttir ve azalt fonksiyonları devreye sok diyorum kısaca. Tabi bu sırada otomatik olarak arttir ve azalt fonksiyonları slicer tarafından bu compenente import ediliyor.
JavaScript:
import { useDispatch, useSelector } from 'react-redux';
import { arttir, azalt } from './Redux/Slicer';
function App() {
const { deger } = useSelector((store) => store.slice);
console.log(deger);
const dispatch = useDispatch();
return (
<div>
<div>{deger}</div>
<div>
<button onClick={() => { dispatch(arttir()) }}>Arttır</button>
<button onClick={() => { dispatch(azalt()) }}>Azalt</button>
</div>
</div>
)
}
export default App;
App.jsx yani ana compenentin son durumu bu. Burada anlamayacağınız tek şey dispatch ve selector kısmı olur bu konuyu da boşa anlatmıyoruz değil mi babayiğit
Gelelim ekrana iki adet buton bir değer (1) vardı. Şimdi sırayla tuşlara basayım.
Arttıra biraz abandım ve 15 oldu değer. Biraz da azalt'a basayim.
15'ten 5'e indirdik. Yani kısaca fonksiyonlar amaca hizmet ediyor
Bugün aslında çok önemli bir react bileşeni öğrendik. Teker teker propsmuş childmiş uğraşmayacağız. Tek bir yere (store) değer ve fonksiyon yollayıp ihtiyacımız olduğunda oradan çekip kullanacağız. İleriki konularda api için asenkron işlemlerinde de bu işleme benzer işlemler yapacağız. Bu yüzden bu konuyu iyice öğrenmenizde fayda var. Şimdilik bu kadar başka bir konuda görüşmek üzere.


