Redux Toolkit Nedir?
Redux Toolkit, Redux'u daha kolay ve verimli bir şekilde kullanmamızı sağlayan bir araçtır. Redux Toolkit’in en önemli özelliklerinden biri slice
mantığıdır. Slice
, Redux’ta state ve reducer’ları bir arada tanımlamayı kolaylaştıran bir yapı sunar.
Slice Nedir?
Bir slice, belirli bir state dilimi için action’ları, reducer’ları ve başlangıç durumunu (initial state) bir arada tanımlar. Redux Toolkit ile oluşturulan bir slice, genellikle bir modülün ya da bir bileşenin state yönetimini kapsar.
Slice Nasıl Çalışır?
edux Toolkit ile slice oluşturmak için createSlice
fonksiyonu kullanılır. Bu fonksiyon, reducer, action ve initial state’i tek bir yapı altında toplar.
import { createSlice } from '@reduxjs/toolkit';
// Başlangıç durumu
const initialState = {
counter: 0,
};
// createSlice ile slice oluşturma
const counterSlice = createSlice({
name: 'counter', // Slice'ın adı
initialState, // Başlangıç durumu
reducers: { // Reducer'lar ve action'lar
increment: (state) => {
state.counter += 1; // state güncellenirken mutasyon yöntemi kullanılabilir
},
decrement: (state) => {
state.counter -= 1;
},
incrementByAmount: (state, action) => {
state.counter += action.payload;
}
}
});
// Oluşturulan action'ları ve reducer'ı dışa aktar
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
Slice Mantığının Faydaları
-
Kodun Düzenlenmesi: Her bir slice, belirli bir state dilimini yönettiği için kod daha organize hale gelir. Her bileşen ya da modül için ayrı slice'lar oluşturabilirsiniz.
-
Boilerplate Kodun Azaltılması: Redux Toolkit ile birlikte gelen
createSlice
, action type tanımlamayı ve reducer yazmayı kolaylaştırır, böylece boilerplate kodu azaltır. -
Mutasyon Desteği:
createSlice
ile yazılan reducer’larda, state’in mutasyon yöntemiyle güncellenmesine izin verilir. Bu, aslında state'in immutability'sini bozmadan yapılır çünkü Redux Toolkit,Immer
kütüphanesini kullanarak arka planda bu mutasyonları güvenli hale getirir.
Slice Kullanım Örneği
Redux Toolkit ve slice kullanarak bir sayacı yönetelim:
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
// Store oluşturma
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
Bileşende Slice Kullanımı
Slice'ı bileşenlerde kullanmak oldukça basittir. Redux Toolkit, useDispatch
ve useSelector
gibi hook'larla entegrasyonu kolaylaştırır.
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './counterSlice';
const CounterComponent = () => {
const counter = useSelector((state) => state.counter.counter);
const dispatch = useDispatch();
return (
<div>
<h1>Counter: {counter}</h1>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
<button onClick={() => dispatch(incrementByAmount(5))}>Increment by 5</button>
</div>
);
};
export default CounterComponent;
Redux Toolkit’in sunduğu slice mantığı, Redux'u daha kolay ve düzenli hale getirir. State, action ve reducer’ların bir arada tanımlanması, kodun modüler yapıda organize edilmesini sağlar ve boilerplate kodunu azaltır. Özellikle büyük projelerde, slice’lar sayesinde state yönetimi daha yönetilebilir ve okunabilir hale gelir.
initialState, reducers, extraReducers Kavramları
initialState
, bir Redux slice'ında ya da reducer'da, uygulamanın başlangıçtaki durumunu tanımlayan nesnedir. Yani, Redux store oluşturulduğunda ya da belirli bir slice ilk kez çalıştırıldığında state'in ne olacağını belirler.
Örneğin, bir sayaç uygulamasında initialState
, sayacın başlangıç değerini temsil eder:
const initialState = {
counter: 0,
};
Bu durumda, counter
state'i uygulama başladığında 0
olacak şekilde ayarlanmıştır. Eğer bir kullanıcı increment
action'ını dispatch ederse, bu state 1
olarak güncellenir. Ancak, uygulama başladığında veya reducer ilk kez çağrıldığında, initialState
bu başlangıç durumunu sağlar.
Kullanım Örneği
const counterSlice = createSlice({
name: 'counter',
initialState: { counter: 0 }, // initialState burada tanımlanır
reducers: {
increment: (state) => {
state.counter += 1;
},
decrement: (state) => {
state.counter -= 1;
},
},
});
Bu örnekte, initialState
, sayacın başlangıç değerini 0
olarak tanımlar. Uygulama başladığında, counter
state'i bu başlangıç durumuna sahip olacaktır.
Reducers
, Redux'ta state'i nasıl değiştireceğimizi tanımlayan saf fonksiyonlardır. Bir action dispatch edildiğinde, ilgili reducer çağrılır ve bu reducer, mevcut state'i alarak belirli bir action'a göre yeni bir state döner. Reducer'lar, gelen action'ı değerlendirir ve buna göre state'i günceller.
Reducer'ın Özellikleri
-
Saf Fonksiyonlar: Reducer'lar saf (pure) fonksiyonlardır, yani aynı girdiyle her zaman aynı çıktıyı üretirler ve girdiyi (state) mutasyona uğratmazlar.
-
State Güncellemesi: Reducer, mevcut state ve action'a göre yeni bir state döner. Mevcut state'in doğrudan değiştirilmesi yerine, yeni bir state objesi oluşturulur ve geri döndürülür.
-
Action'a Dayalı: Reducer'lar, dispatch edilen action'ın
type
değerine göre belirli işlemler yapar. Her action belirli birtype
alanına sahiptir ve reducer'lar bu alanı kontrol ederek ilgili işlemi gerçekleştirir.
Reducer'ın Çalışma Mantığı
Bir action dispatch edildiğinde, Redux store bu action'ı alır ve ilgili reducer'ı çalıştırır. Reducer, action'ın type
değerine göre mevcut state'i alır ve yeni bir state döndürür.
const counterReducer = (state = { counter: 0 }, action) => {
switch (action.type) {
case 'INCREMENT':
return { ...state, counter: state.counter + 1 };
case 'DECREMENT':
return { ...state, counter: state.counter - 1 };
default:
return state; // Tanınmayan bir action'da mevcut state döner
}
};
Reducer'ın Adımları
-
Mevcut State ve Action: Reducer, mevcut state ve dispatch edilen action'ı parametre olarak alır.
-
Action Type Kontrolü: Reducer, action'ın
type
değerini kontrol eder ve bu değere göre hangi işlemi yapacağını belirler. -
Yeni State Döndürme: Reducer, state'i mutasyona uğratmadan, mevcut state'in bir kopyasını oluşturur ve action'a göre güncellemeler yaparak yeni bir state döner.
Reducer'lar, Redux'ta state'in nasıl değişeceğini tanımlayan fonksiyonlardır. Dispatch edilen action'ları alır, bu action'lara göre state'i günceller ve yeni bir state döner. Reducer'lar saf fonksiyonlar oldukları için aynı girdilerle her zaman aynı sonucu üretirler, bu da uygulamanın tahmin edilebilir ve kontrol edilebilir olmasını sağlar.
extraReducers
, Redux Toolkit'te createSlice
fonksiyonu içinde kullanılan ve slice'ın dışında tanımlanan action'ları işlemesini sağlayan bir yapılandırma alanıdır. Normal reducers
bölümü, slice içinde tanımlanan action'ları işlerken, extraReducers
slice'ın dışındaki action'lara tepki vermek için kullanılır. Bu, özellikle asenkron işlemler (createAsyncThunk
ile oluşturulan action'lar gibi) için faydalıdır.
extraReducers
Nasıl Çalışır?
Bir slice’ın kendi action'larının dışında başka action'larla da state'i güncellemesi gerektiğinde extraReducers
kullanılır. Örneğin, bir slice'ın fulfilled
, pending
, ve rejected
durumlarına göre state'i güncellemesi gerektiğinde extraReducers
bölümüne bu action'lar eklenir.
extraReducers
Örneği
Aşağıda, bir createAsyncThunk
ile oluşturulmuş asenkron bir action ve bunun extraReducers
ile bir slice'a nasıl eklendiği gösterilmiştir.
1. Asenkron İşlem Tanımlama (createAsyncThunk)
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
// Kullanıcı verilerini getiren asenkron işlem
export const fetchUser = createAsyncThunk(
'user/fetchUser',
async (userId) => {
const response = await fetch(`/api/user/${userId}`);
return response.json();
}
);
2. Slice Oluşturma ve extraReducers
Kullanımı
const userSlice = createSlice({
name: 'user',
initialState: {
data: null,
status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed'
error: null
},
reducers: {
// Sadece bu slice'a ait olan action'lar burada tanımlanır
},
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading';
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded';
state.data = action.payload;
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
}
});
export default userSlice.reducer;
extraReducers
ve builder
Kullanımı
Redux Toolkit’in yeni sürümlerinde extraReducers
'ı tanımlarken builder
fonksiyonu önerilir. builder
kullanımı daha esnek bir yapı sunar ve zincirleme (.addCase
) yöntemiyle farklı action'lar eklemeyi sağlar.
extraReducers
Ne Zaman Kullanılır?
- Asenkron İşlemler:
createAsyncThunk
ile tanımlanan asenkron işlemler için. - Dış Action'lar: Bir slice'ın başka bir slice veya modülden gelen action'ları işlemesi gerektiğinde.
- Ortak State Güncellemeleri: Birden fazla slice'ın aynı action'ı işlemesi gerektiğinde.
extraReducers
, bir Redux slice'ın kendi action'ları dışındaki action'ları işlemesini sağlayan bir yapıdır. Bu, özellikle asenkron işlemler ve diğer slice'lardan gelen action'lar için gereklidir. extraReducers
, Redux uygulamalarında daha esnek ve modüler bir state yönetimi sağlar.
- React
Tepkini Göster
- 6
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
Yorumlar
Sende Yorumunu Ekle