React'te state yönetimi için useReducer hook'u, özellikle birden fazla alt değere sahip veya birbirine bağlı state güncellemeleri içeren durumlarda useState'e güçlü bir alternatiftir. Redux benzeri bir desen sunar; bir reducer fonksiyonu ve action'lar aracılığıyla state'i günceller. Bu yazıda, useReducer hook'unu adım adım nasıl kullanacağınızı, tipik kullanım senaryolarını ve yaygın hatalardan nasıl kaçınacağınızı göreceksiniz.
1. useReducer Nedir ve Neden Kullanılır?
useReducer, React'ın yerleşik bir hook'udur. Üç temel bileşeni vardır:
- Reducer fonksiyonu: Mevcut state ve bir action alır, yeni state döndürür.
- Initial state: Başlangıç değeri.
- Dispatch fonksiyonu: Action'ları reducer'a göndermek için kullanılır.
Karmaşık formlar, çok adımlı sihirbazlar, alışveriş sepeti ve benzeri yapılar için idealdir. useState'in yetersiz kaldığı durumlarda kodun okunabilirliğini ve test edilebilirliğini artırır. Daha önce React useState Hook ile State Yönetimi yazısında temel kullanımı görmüştük; şimdi daha ileri bir seviyeye geçiyoruz.
2. Adım Adım useReducer Kullanımı
- Reducer fonksiyonunu tanımlayın
Reducer, geçerli state ve action parametrelerini alır. Action genellikle birtypealanı içerir. Örnek bir sayaç reducer'ı:function counterReducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error('Bilinmeyen action'); } } - Initial state'i belirleyin
Genellikle bir nesne veya basit bir değer olabilir:const initialState = { count: 0 }; - useReducer hook'unu çağırın
Component içinde:const [state, dispatch] = useReducer(counterReducer, initialState); - Dispatch ile action gönderin
Kullanıcı etkileşimlerinde dispatch çağırın:dispatch({ type: 'increment' });
Bu temel adımlar, her türlü useReducer kullanımının temelini oluşturur. Şimdi daha gerçekçi bir örnek üzerinden ilerleyelim.
3. Karmaşık State Örneği: Alışveriş Sepeti
Bir alışveriş sepeti uygulaması düşünelim. Sepette ürünler, toplam fiyat ve adet bilgisi olsun.
function cartReducer(state, action) {
switch (action.type) {
case 'add_item':
return {
...state,
items: [...state.items, action.payload],
total: state.total + action.payload.price
};
case 'remove_item':
const updatedItems = state.items.filter(item => item.id !== action.payload.id);
return {
...state,
items: updatedItems,
total: updatedItems.reduce((sum, item) => sum + item.price, 0)
};
default:
return state;
}
}
const initialCart = { items: [], total: 0 };
function ShoppingCart() {
const [cart, dispatch] = useReducer(cartReducer, initialCart);
const addItem = (item) => dispatch({ type: 'add_item', payload: item });
const removeItem = (item) => dispatch({ type: 'remove_item', payload: item });
// ... render cart
}
Burada birden çok state alanı (items ve total) tek bir reducer altında yönetilir. Her action net bir iş yapar ve state'in nasıl değişeceği açıktır.
4. useReducer vs useState: Ne Zaman Hangisi?
| Kriter | useState | useReducer |
|---|---|---|
| State yapısı | Basit (string, number, boolean) | Karmaşık (nesne, dizi) |
| Güncelleme mantığı | Doğrudan setter | Action tipine göre merkezi reducer |
| Test edilebilirlik | Daha zor | Reducer saf fonksiyon olduğu için kolay |
| Ölçeklenebilirlik | Küçük bileşenler | Büyük, karmaşık state'ler |
Eğer state'iniz birden çok alt değer içeriyorsa veya güncelleme mantığı karışıksa useReducer tercih edilmelidir. Aksi halde useState yeterlidir. Bu ayrımı iyi yapmak, gereksiz karmaşıklıktan kaçınmanızı sağlar.
5. Sık Yapılan Hatalar ve Dikkat Edilmesi Gerekenler
- Action type'larını string sabit olarak kullanmayın: Büyük projelerde hata yapma riskini azaltmak için action type'larını sabit değişkenlerde tanımlayın.
- Reducer dışında state'i değiştirmeyin: Reducer saf olmalı, yan etkilerden kaçının. Örneğin,
cart.items.push()yerine yeni dizi oluşturun. - default case'de hata fırlatın: Bu, geçersiz action'ları erken yakalamanızı sağlar.
- useReducer'ı context ile birleştirin: Global state için
useReducerveContextbirlikte kullanılabilir. Ancak dikkatli olun, gereksiz yeniden render'lara yol açabilir. Daha fazla bilgi için React useEffect Cleanup Fonksiyonu ile Bellek Sızıntılarını Önleme yazısına göz atabilirsiniz.
6. useReducer ile Asenkron İşlemler
useReducer kendisi asenkron değildir. Ancak, API çağrıları gibi yan etkileri useEffect içinde yönetip dispatch edebilirsiniz. Örneğin:
useEffect(() => {
fetch('/api/items')
.then(res => res.json())
.then(data => dispatch({ type: 'set_items', payload: data }));
}, []);
Bu yapı, state yönetimini reducer'da tutarken veri çekme işlemini useEffect'e bırakır.
7. Sonuç
useReducer, React uygulamalarında karmaşık state mantığını düzenli ve yönetilebilir kılar. Redux gibi harici kütüphanelere ihtiyaç duymadan benzer bir desen sunar. Bu rehberdeki adımları izleyerek projelerinizde useReducer'ı etkin bir şekilde kullanabilirsiniz. Unutmayın, doğru aracı seçmek kod kalitesini ve bakım kolaylığını doğrudan etkiler.
Sık Sorulan Sorular
useReducer hook'u ne işe yarar?
useReducer, React'te karmaşık state mantığını yönetmek için kullanılan bir hook'tur. Bir reducer fonksiyonu ve action'lar aracılığıyla state'i günceller, böylece kod okunabilirliğini ve test edilebilirliğini artırır.
useState yerine ne zaman useReducer kullanmalıyım?
State birden çok alt değere sahipse veya güncelleme mantığı karmaşıksa (örneğin alışveriş sepeti) useReducer tercih edilmelidir. Basit state'ler için useState yeterlidir.
useReducer ile Redux arasındaki fark nedir?
useReducer React'ın yerleşik bir hook'udur ve sadece bir bileşen veya useContext ile paylaşılan state için uygundur. Redux ise harici bir kütüphane olup middleware, devtools ve büyük ölçekli state yönetimi için daha kapsamlı çözümler sunar.
useReducer ile asenkron işlemler yapabilir miyim?
useReducer'ın kendisi asenkron değildir, ancak useEffect içinde API çağrıları yapıp sonuçları dispatch edebilirsiniz. Bu sayede veri çekme işlemleri state yönetiminden ayrılır.
useReducer'da action type'larını nasıl tanımlamalıyım?
Hataları önlemek için action type'larını string sabitler olarak (örn. const ADD_ITEM = 'add_item') tanımlayın. Bu, büyük projelerde bakımı kolaylaştırır.





