Merhaba arkadaşlar, bugün başımı çok ağrıtan ve React öğrenirken hepimizin mutlaka takıldığı bir konudan bahsedeceğim. useState hook'unun setter fonksiyonunu, aynı render döngüsü içinde peş peşe çağırdığınızda, ilk çağrıdaki güncellemenin hemen state'e yansımadığını fark ettiniz mi? Ben bu durumu ilk gördüğümde, "kodum neden matematiksel olarak doğru sonucu vermiyor?" diye kafayı yemiştim. Özellikle bir sayaç artırma işlemi veya bir diziye ardışık eklemeler yaparken bu sorunla karşılaşabilirsiniz.
Karşılaştığım Sorun
Diyelim ki, bir `count` state'imiz var ve bir butona tıklandığında bu sayacı 3 kere artırmak istiyoruz. Saf düşünceyle, setCount'u üç kere çağırmak mantıklı geliyor değil mi? İşte tam da burada bataklığa saplanıyorsunuz.
Bu kodu çalıştırdığınızda, butona her tıklamada sayacın sadece 1 arttığını göreceksiniz. Sebebi, React'in performans için state güncellemelerini toplu (batch) işlemesi ve `handleClick` fonksiyonundaki tüm `count` değerlerinin, o fonksiyon çağrıldığı andaki değer olan 0'a referans etmesi. Yani her `setCount(count + 1)`, aslında `setCount(0 + 1)` anlamına geliyor.
Functional Update Çözümü
Neyse ki React, bu durumdan kurtulmak için harika bir çözüm sunuyor: Functional (Fonksiyonel) Update. Setter fonksiyonuna, sadece yeni bir değer değil, bir de fonksiyon verebiliyoruz. Bu fonksiyon, React tarafından en güncel state değerini parametre olarak alır ve yeni state'i döndürmemizi sağlar.
İşte şimdi oldu! Butona her tıkladığımızda sayaç 3 artacak. Çünkü her `setCount` çağrısı, bir önceki güncellemeden çıkan en güncel `prevCount` değerini alıyor ve ona işlem yapıyor. Bu, aynı render içinde birbiri ardına gelen aynı state güncellemeleri için kurtarıcı bir yöntem.
Gerçek Hayat Senaryosu ve Uyarı
Bu yöntem sadece sayı artırmak için değil, dizileri veya objeleri güncellerken de hayat kurtarıcı. Özellikle state, önceki değere bağlıysa MUTLAKA functional update kullanın.
Önemli Uyarı: Eğer güncellemeleriniz birbirinden tamamen bağımsızsa (örneğin, iki farklı input alanı), functional update kullanmanıza gerek yok. Direkt değer atayabilirsiniz.
Sizler de React'te state güncellerken böyle "sinsice" hatalar yapıp sonra functional update ile kurtulduğunuz anlar oldu mu? Ya da state yönetimi için useReducer gibi farklı bir hook'u bu tarz senaryolarda tercih ediyor musunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!
Diyelim ki, bir `count` state'imiz var ve bir butona tıklandığında bu sayacı 3 kere artırmak istiyoruz. Saf düşünceyle, setCount'u üç kere çağırmak mantıklı geliyor değil mi? İşte tam da burada bataklığa saplanıyorsunuz.
JavaScript:
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1); // count 0 olduğunu düşünür
setCount(count + 1); // Yine count 0 olduğunu düşünür!
setCount(count + 1); // Ve yine 0!
// Sonuç: count 1 olur, 3 değil!
};
return (
<div>
<p>Sayaç: {count}</p>
<button onClick={handleClick}>3 Artır</button>
</div>
);
}
Bu kodu çalıştırdığınızda, butona her tıklamada sayacın sadece 1 arttığını göreceksiniz. Sebebi, React'in performans için state güncellemelerini toplu (batch) işlemesi ve `handleClick` fonksiyonundaki tüm `count` değerlerinin, o fonksiyon çağrıldığı andaki değer olan 0'a referans etmesi. Yani her `setCount(count + 1)`, aslında `setCount(0 + 1)` anlamına geliyor.
Neyse ki React, bu durumdan kurtulmak için harika bir çözüm sunuyor: Functional (Fonksiyonel) Update. Setter fonksiyonuna, sadece yeni bir değer değil, bir de fonksiyon verebiliyoruz. Bu fonksiyon, React tarafından en güncel state değerini parametre olarak alır ve yeni state'i döndürmemizi sağlar.
JavaScript:
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
// Functional Update kullanıyoruz
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
// Her biri bir önceki güncellemenin sonucuyla çalışır.
// Sonuç: count 3 olur!
};
return (
<div>
<p>Sayaç: {count}</p>
<button onClick={handleClick}>3 Artır</button>
</div>
);
}
İşte şimdi oldu! Butona her tıkladığımızda sayaç 3 artacak. Çünkü her `setCount` çağrısı, bir önceki güncellemeden çıkan en güncel `prevCount` değerini alıyor ve ona işlem yapıyor. Bu, aynı render içinde birbiri ardına gelen aynı state güncellemeleri için kurtarıcı bir yöntem.
Bu yöntem sadece sayı artırmak için değil, dizileri veya objeleri güncellerken de hayat kurtarıcı. Özellikle state, önceki değere bağlıysa MUTLAKA functional update kullanın.
JavaScript:
const [list, setList] = useState(['elma', 'armut']);
const addItems = () => {
// BU YANLIŞ: 'list' her seferinde başlangıçtaki haliyle aynı.
// setList([...list, 'muz']);
// setList([...list, 'çilek']); // Sadece 'elma', 'armut', 'çilek' ekler.
// BU DOĞRU:
setList(prevList => [...prevList, 'muz']);
setList(prevList => [...prevList, 'çilek']); // 'muz' da dahil olur.
};
Önemli Uyarı: Eğer güncellemeleriniz birbirinden tamamen bağımsızsa (örneğin, iki farklı input alanı), functional update kullanmanıza gerek yok. Direkt değer atayabilirsiniz.
Sizler de React'te state güncellerken böyle "sinsice" hatalar yapıp sonra functional update ile kurtulduğunuz anlar oldu mu? Ya da state yönetimi için useReducer gibi farklı bir hook'u bu tarz senaryolarda tercih ediyor musunuz? Yorumlarda deneyimlerinizi paylaşın, tartışalım!