aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Web Geliştirme

React useState ile State Yönetimi Temelleri

react usestate, bir fonksiyon bileşeni içinde değişen veriyi (state) saklamanın en temel yoludur. Bir sayaç, bir form alanı, bir açılır menünün açık/kapalı durumu… kullanıcı etkileşimiyle değişen her şey state'tir ve React'in bu değişikliği ekrana yansıtması için onu useState ile tutman gerekir. Sıradan bir değişkeni güncellemek React'i tetiklemez; useState ise hem değeri saklar hem de değiştiğinde bileşeni yeniden render eder.

useState nasıl çalışır?

useState bir başlangıç değeri alır ve iki elemanlı bir dizi döndürür: güncel değer ve bu değeri değiştiren fonksiyon. Dizi destructuring ile ikisini birden adlandırırız:

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount(count + 1)}>
      Tıklandı: {count}
    </button>
  );
}

Burada count güncel değeri, setCount ise onu değiştiren fonksiyondur. useState(0) içindeki 0 yalnızca ilk render'da kullanılır; sonraki render'larda React önceki değeri hatırlar. İsimlendirme tamamen senin; gelenek olarak [x, setX] kalıbı kullanılır.

State'i asla doğrudan değiştirme

React'te en sık yapılan hata, state'i doğrudan mutasyona uğratmaktır. State'i değiştirmenin tek yolu set fonksiyonunu çağırmaktır. Aşağıdaki gibi doğrudan atama yapmak ekranı güncellemez:

// YANLIŞ — React bunu fark etmez
count = count + 1;

// DOĞRU — yeniden render tetiklenir
setCount(count + 1);

Aynı kural nesne ve diziler için de geçerlidir. Mevcut nesneyi değiştirmek yerine yeni bir nesne oluşturursun. Bunun nedeni, React'in değişikliği referans karşılaştırmasıyla (eski değer ile yeni değer aynı mı) algılamasıdır; aynı referansı değiştirirsen React bir şeyin değiştiğini anlamaz.

const [user, setUser] = useState({ ad: "Ada", yas: 30 });

// YANLIŞ
user.yas = 31;
setUser(user);

// DOĞRU — spread ile yeni nesne
setUser({ ...user, yas: 31 });

Fonksiyonel güncelleme: neden ve ne zaman?

Set fonksiyonuna doğrudan bir değer vermek yerine, önceki state'i argüman alan bir fonksiyon da verebilirsin. Buna fonksiyonel güncelleme denir ve yeni değer eski değere bağlı olduğunda en güvenli yöntemdir:

// önceki değere bağlı: fonksiyonel biçim tercih edilir
setCount(prev => prev + 1);

Fark, aynı olayda state'i birden çok kez güncellediğinde ortaya çıkar. Şu iki örneği karşılaştır:

// Bu, sayacı yalnızca 1 artırır
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);

// Bu, sayacı 3 artırır
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);

İlk blokta count o render'daki sabit değerdir (örneğin 0), bu yüzden üç çağrı da 0 + 1 hesaplar. Fonksiyonel biçimde ise her çağrı bir önceki güncellemenin sonucunu alır, bu yüzden sonuç doğru birikir.

Batch (toplu) güncelleme

React, aynı olay işleyicisi içindeki birden fazla state güncellemesini tek bir render'da toplar; buna batching denir. Yani üç farklı set çağrısı yapsan bile bileşen üç kez değil, bir kez yeniden render edilir. Bu, performansı artırır ve ekranda yarım kalmış ara durumların görünmesini engeller.

function handleClick() {
  setAcik(true);
  setSayac(s => s + 1);
  setMesaj("güncellendi");
  // üçü birden tek render'da uygulanır
}

React 18 ile birlikte bu davranış yalnızca olay işleyicilerinde değil, setTimeout, Promise ve diğer asenkron callback'lerde de geçerli hale geldi (otomatik batching). Önemli bir nokta: set fonksiyonunu çağırdıktan hemen sonra state değişkeni eski değerini taşır, çünkü güncelleme bir sonraki render'da etkili olur.

setCount(count + 1);
console.log(count); // hâlâ eski değer — render henüz olmadı

Diziler ve nesnelerle pratik kalıplar

Karmaşık state'te de kural aynı: kopyala, değiştir, set et. Sık kullanılan kalıplar:

  • Listeye eleman ekleme: setItems(prev => [...prev, yeni])
  • Listeden çıkarma: setItems(prev => prev.filter(i => i.id !== id))
  • Bir elemanı güncelleme: setItems(prev => prev.map(i => i.id === id ? { ...i, done: true } : i))

State çok dallanıyor ve birbirine bağlı birçok alan içeriyorsa, useState yerine useReducer daha okunabilir olabilir. Ama günlük işlerin büyük kısmı için useState yeterli ve en sade çözümdür.

Sık Sorulan Sorular

useState ile useRef arasındaki fark nedir?

useState değiştiğinde bileşeni yeniden render eder; ekranda görünmesi gereken veriler içindir. useRef ise değeri render'lar arası saklar ama değiştiğinde render tetiklemez; DOM elemanına erişmek veya render'ı etkilemeyen bir değeri tutmak için kullanılır.

useState'i bir döngü veya koşul içinde çağırabilir miyim?

Hayır. Tüm Hook'lar bileşenin en üst seviyesinde, her render'da aynı sırada çağrılmalıdır. Koşullu ya da döngü içinde çağırmak React'in state'leri eşleştirmesini bozar ve hata verir.

Başlangıç değeri pahalı bir hesaplamaysa ne yapmalıyım?

Başlangıç değerini doğrudan vermek yerine bir fonksiyon geç: useState(() => pahaliHesap()). Bu "lazy initializer" yalnızca ilk render'da çalışır, sonraki render'larda tekrar hesaplanmaz.

State yönetimini doğru kurmak, bakımı kolay bir arayüzün temelidir. React tabanlı bir proje geliştiriyor veya mevcut bir arayüzü iyileştirmek istiyorsan benimle iletişime geç — birlikte sağlam bir mimari kuralım.

Bu kategorideki tüm yazılar →

Devamı için