State'i yukarı taşımak (lifting state up), state'i onu paylaşması gereken bileşenlerden çıkarıp en yakın ortak ebeveynlerine taşımak demektir. Ebeveyn değeri tutar, onu bir prop olarak aşağı aktarır ve çocukların onu değiştirmek için çağırdığı bir fonksiyon aktarır; böylece her çocuk state'in tek bir kopyasından render eder.
Herhangi bir paneldeki "Show"a tıkla: o açılır, açık olan kapanır. Aynı anda yalnızca bir panel açık olabilir, çünkü buna paneller kendileri karar vermez. openIndex'i App tutar ve her Panel yalnızca isOpen'ı ve bir onOpen fonksiyonunu alır.
Sorun: aynı fikirde olması gereken state
Her panelin kendi isOpen state'ine sahip olduğu bariz sürümden başla. Her panel çalışır, ama paneller birbirinden habersizdir, bu yüzden ikisinin aynı anda açık olmasını hiçbir şey engellemez.
İki paneli de aç: birlikte açık kalırlar. React'te state onu bildiren bileşene özeldir, bu yüzden bir kardeş onu okuyamaz ya da sıfırlayamaz. İki bileşenin aynı fikirde olması gerektiğinde state ikisinin de üstünde yaşamalıdır.
Üç adımda state'i yukarı taşımak
İkinci örneği birinciye dönüştürmek üç düzenleme alır.
- State'i çocuktan kaldır.
PaneliçindekiuseState'i sil ve bunun yerineisOpen'ı props'tan oku. Çocuk artık açık olup olmadığına karar vermez. - Ebeveynden değeri ve onu değiştirmenin bir yolunu aktar.
Panel,isOpen'ı ve bironOpencallback'ini alır. Çocuk düğmesine tıklandığındaonOpen()'ı çağırır; ebeveynin bununla ne yaptığını bilmez. - State'i ortak ebeveyne ekle.
App,openIndex'i bildirir ve onu her panel için props'a çevirir:isOpen={openIndex === 1}veonOpen={() => setOpenIndex(1)}.
En yakın ortak ebeveyn, state'e ihtiyaç duyan tüm bileşenleri render eden en alttaki bileşendir. Burada bu App'tir. Paneller bir Faq bileşeninin içinde dursaydı state daha yükseğe değil, Faq'ya giderdi.
Taşımadan sonra Panel, kontrollü bir input'la aynı anlamda ebeveyni tarafından kontrol edilir: props'un söylediğini gösterir ve değişiklikleri bir callback aracılığıyla bildirir. Kontrollü ve kontrolsüz bileşenler sayfası aynı fikri form öğeleri için anlatıyor.
Tek doğruluk kaynağı
Ekranın iki parçası aynı olguyu gösterdiğinde o olguyu bir kez sakla ve diğer her şeyi ondan hesapla. Bir sıcaklık dönüştürücü klasik örnektir: Celsius ve Fahrenheit input'ları her zaman aynı fikirde olmalıdır, bu yüzden her biri kendi sayısını tutamaz.
Herhangi bir alana yaz, diğeri onu takip eder. State tek bir olgudur: kullanıcının en son yazdığı sayı ve hangi ölçekte olduğu. Diğer alan render sırasında ondan hesaplanır, bu yüzden yazdığın alan her zaman tam olarak yazdığını korur. Başlangıç state'ini { value: '212', scale: 'f' } yap; input'ların altındaki mesaj "Water boils." olur.
Bir Celsius sayısını ve bir Fahrenheit sayısını iki state parçasında tutmak her işleyicinin ikisini de güncellemesi gerektiği anlamına gelirdi ve bir işleyici ilk unuttuğunda iki input farklı şeyler söylerdi. Saklanan tek bir değer kendisiyle çelişemez.
Setter'ı aşağı aktarmak
Bir çocuk ebeveynin state'ini yalnızca ebeveynin ona verdiği bir fonksiyon aracılığıyla değiştirebilir. Setter'ın kendisini (onSelect={setColor}) ya da daha fazlasını yapan bir fonksiyonu (onOpen={() => setOpenIndex(1)}) aktarabilirsin. Prop'a setSelected yerine onSelect ya da onChange gibi olay tarzı bir ad vermek, çocuğun ebeveynin değeri nasıl sakladığından habersiz kalmasını sağlar; böylece ebeveyn bunu daha sonra çocuğa dokunmadan değiştirebilir.
ColorPicker ve Preview birbiriyle hiç konuşmaz. Seçici bir seçimi yukarı bildirir, App onu saklar ve yeni değer ikisine de aşağı akar.
State ne zaman yukarı taşınmamalı
Taşımanın bir maliyeti vardır. State bir ebeveynde yaşadığında her değişiklik ebeveyni ve varsayılan olarak, state'i kullanmayanlar dahil tüm çocuklarını render eder. Yalnızca en yakın ortak ebeveyne kadar taşı ve yalnızca bir bileşenin kullandığı state'i o bileşenin içinde bırak.
Kutuya yaz ve konsolu izle: her tuş vuruşunda yalnızca SearchBox render olur. Şimdi query'yi App'e taşı ve SearchBox'a props olarak aktar. Her tuş vuruşu artık ProductList'i de kaydeder, liste sorguyu kullanmasa bile. Liste sorguya göre filtreleme yapsaydı taşımak doğru karar olurdu, çünkü o zaman iki bileşen de aynı değere bağlı olurdu.
Sorulacak soru "bu değeri kimin okuması gerekiyor?" sorusudur. Cevap tek bir bileşense state orada kalır. Birkaç bileşense en yakın ortak ebeveynlerine gider.
Taşıma fazla ileri gittiğinde
Bazen en yakın ortak ebeveyn ağacın çok yukarısındadır ve değerin onu sadece ileten birkaç bileşenden geçirilmesi gerekir. Bu prop drilling'dir. Birkaç katman props sorun değildir ve takip etmesi kolaydır. Aynı değer birçok katmandan geçtiğinde ya da neredeyse her bileşenin ona ihtiyacı olduğunda (oturum açmış kullanıcı, tema, dil) onu elle aktarmak yerine useContext ile oku. Context değerin çocuklara nasıl ulaştığını değiştirir; state'in kendisi hâlâ tek bir ebeveynde yaşar, yani hâlâ yukarı taşınmıştır.
Sıkça Sorulan Sorular
React'te state'i yukarı taşımak ne demektir?
Bir state parçasını onu kullanan bileşenlerden en yakın ortak ebeveynlerine taşımak. State'in sahibi ebeveyndir; değeri ve onu değiştirecek bir fonksiyonu props olarak çocuklara aşağı aktarır.
React'te iki kardeş bileşen state'i nasıl paylaşır?
Kardeşler birbirinin state'ini okuyamaz. State'i ortak ebeveynlerine koy, değeri ikisine de aktar ve onu değiştirene bir setter (ya da onChange gibi bir işleyici) aktar. Böylece iki kardeş de aynı değerden render eder.
Bir çocuk bileşen ebeveynin state'ini nasıl günceller?
Ebeveyn bir fonksiyonu prop olarak aktarır, örneğin onSelect={setSelected} ya da onSelect={(id) => setSelected(id)}, çocuk da onu çağırır. State ebeveynde kalır; çocuk yalnızca değişikliği ister.
State'i ne zaman yukarı taşımamalıyım?
State'i yalnızca bir bileşen kullanıyorsa. Onu gerektiğinden yükseğe taşımak ebeveynin her değişiklikte render olmasına yol açar ve props'u bununla ilgilenmeyen bileşenlere yayar. State'i kullanıldığı yere olabildiğince yakın tut.
State'i fazla yukarı taşımanın alternatifi nedir?
Aynı props'u birçok katmandan geçirdiğini fark edersen paylaşılan değeri bunun yerine context ile (useContext) oku ya da ona ihtiyaç duyan bileşenler birbirine daha yakın olacak şekilde yeniden düzenle.