useState, bir bileşenin render'lar arasında bir şeyi hatırlamasını sağlayan hook'tur: bir sayı, bir input'taki metin, bir menünün açık olup olmadığı. Setter'ını her çağırdığında React bileşeni yeni değerle yeniden render eder.
Düğmeye tıkla, sonra editörde useState(0) ifadesini useState(10) olarak değiştir. Önizleme yeniden derlenir ve sayı 10'dan başlar.
Sözdizimi
const [value, setValue] = useState(initialValue);
initialValueyalnızca ilk render'da kullanılır. Sonraki her render'da React onu yok sayar ve sakladığı değeri geri verir.valuebu render için mevcut değerdir.setValuedeğeri değiştirir ve yeni bir render planlar.
Adlar sana ait. useState iki öğeli bir dizi döndürür ve köşeli parantezler onu açar, bu yüzden [isOpen, setIsOpen] ve [email, setEmail] aynı kalıptır.
useState'i bileşeninin en üst düzeyinde çağır; asla bir döngü, bir koşul ya da iç içe bir fonksiyon içinde değil. React her çağrıyı sakladığı değerle çağrıların sırasına göre eşleştirir, bu yüzden bu sıra her render'da aynı olmalıdır (bkz. hook kuralları).
Birden çok state parçası
Bir bileşen useState'i ihtiyacı kadar çağırabilir. Her çağrı kendi bağımsız değeridir.
State bir anlık görüntüdür
Setter elindeki değişkeni değiştirmez. React'e değerin sonraki render'da ne olması gerektiğini söyler. O render gerçekleşene kadar mevcut render eski değeri görmeye devam eder.
Önizlemenin altındaki konsolu aç ve bir kez tıkla. İşleyici eski değer olan 0'ı yazar, sonra bileşen 1 ile yeni bir render kaydeder. Bir sorun yok: count tüm render boyunca bir sabittir ve sonraki render taze bir tane alır.
Updater fonksiyonları
Anlık görüntü yüzünden setter'ı count + 1 ile üç kez çağırmak üç değil bir ekler: her çağrı 0 + 1 hesaplar. Bunun yerine bir fonksiyon aktar; React her çağrıya bir öncekinin sonucunu verir.
Bir sonraki değer öncekine bağlı olduğunda ve güncelleme doğrudan en son render'dan çalışmayabileceğinde updater biçimini kullan: bir işleyicide birkaç set, bir setInterval callback'i ya da bir efekt.
State'te nesneler ve diziler
React yeniden render edip etmeyeceğine eski ve yeni değeri Object.is ile karşılaştırarak karar verir. Bir nesneyi yerinde değiştirip aynı nesneyi geri aktarırsan karşılaştırma hiçbir şeyin değişmediğini söyler ve ekran olduğu gibi kalır. Her zaman yeni bir nesne ya da dizi aktar.
{ ...user, age: user.age + 1 } her alanı kopyalar ve birini geçersiz kılar. [...tags, 'code'] bir öğe ekler, filter ise bir öğe çıkarır; ikisi de yeni bir dizi döndürür. Dizileri ve nesneleri güncellemek sayfası iç içe nesneleri, bir listedeki tek bir öğeyi düzenlemeyi ve ortaya ekleme yapmayı anlatıyor.
Lazy başlangıç state'i
useState'in argümanı her render'da değerlendirilir, React onu yalnızca ilk seferde kullansa bile. Onu hesaplamak pahalı olduğunda (localStorage okumak, büyük bir metni ayrıştırmak) bir fonksiyon aktar. React onu bir kez, ilk render'da çağırır.
// Runs readSavedNotes() on every render, then throws the result away
const [notes, setNotes] = useState(readSavedNotes());
// Runs it once
const [notes, setNotes] = useState(readSavedNotes);
const [notes, setNotes] = useState(() => readSavedNotes());
State'i bir key ile sıfırlamak
State, bir bileşenin ağaçtaki konumuna aittir. Aynı yerde farklı bir key render edersen React onu yeni bir bileşen olarak ele alır ve state'i baştan başlar. Bu, bir formun düzenlediği şey değiştiğinde onu sıfırlamanın en temiz yoludur.
Bir mesaj yaz, sonra alıcıyı değiştir: taslak temizlenir. key={to}'yu sil ve yeniden dene; metin kalır, çünkü React artık aynı yerde aynı Draft'ı görür.
Yaygın hatalar
State'i ayarladıktan hemen sonra yazdırmak. Yukarıda gösterildiği gibi eski değeri görürsün. Bileşen gövdesinde yazdır ya da önce sonraki değeri bir değişkene hesapla ve onu kullan.
State'i değiştirmek (mutation). user.age++; setUser(user) aynı nesneyi aktarır, bu yüzden hiçbir şey render edilmez. Önce kopyala.
Setter'ı render sırasında çağırmak. <button onClick={setCount(count + 1)}>, render ederken setCount'u çağırır; bu yeniden render eder, bu da onu yeniden çağırır. React bu döngüyü "Too many re-renders" ile durdurur. Bir fonksiyon aktar: onClick={() => setCount(count + 1)}.
Hesaplayabileceğin değerleri saklamak. fullName her zaman first + ' ' + last ise, senkronu kaybedebilecek üçüncü bir state parçası tutmak yerine onu render sırasında hesapla.
Sıkça Sorulan Sorular
useState ne döndürür?
Tam olarak iki öğeli bir dizi: mevcut değer ve onu değiştiren bir fonksiyon. Onları dizi destructuring ile kendin adlandırırsın; kurala göre [thing, setThing].
State'im neden hemen güncellenmiyor?
Setter'ı çağırmak elindeki değişkeni değiştirmez. React'ten bileşeni yeniden render etmesini ister ve yeni değer o sonraki render'da görünür. Mevcut olay işleyicisinin içinde eski değer hâlâ kapsamdadır, bu yüzden setCount(count + 1)'den hemen sonra console.log(count) eski sayıyı yazdırır.
Setter'a ne zaman fonksiyon aktarmalıyım?
Yeni değer eskisine bağlı olduğunda ve onu birden fazla kez ya da bir zamanlayıcının veya efektin içinden ayarladığında. setCount(c => c + 1) her zaman en son değerden başlar, setCount(count + 1) ise bu render'ın gördüğü değerden başlar.
useState bir nesne ya da dizi tutabilir mi?
Evet, ama onu salt okunur olarak ele al. Yeni bir nesne ya da dizi oluştur ve onu setter'a aktar (setUser({ ...user, name }), setItems([...items, item])). Mevcut olanı yerinde değiştirmek bir render tetiklemez.
useState ile useReducer arasındaki fark nedir?
İkisi de state saklar. useState birkaç bağımsız değere uyar. useReducer güncelleme mantığını bir action alan tek bir fonksiyona taşır; bu, birçok olay aynı state'i birbiriyle ilişkili şekillerde değiştirdiğinde daha iyi okunur.