Menu

React'te Prop Drilling: Nedir ve Nasıl Önlenir

Prop drilling, bir prop'u yalnızca daha aşağıdaki bir bileşen kullanabilsin diye onu kullanmayan bileşenlerden geçirmektir. Onu çalıştırılabilir bir örnekte, bir uygulama büyüdükçe neden zarar verdiğini ve çözümlerini denenecekleri sırayla gör: composition, context, sonra bir state kütüphanesi.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Prop drilling, bir prop'u yalnızca ağacın daha aşağısındaki bir bileşen kullanabilsin diye onu kullanmayan bileşenlerden geçirmektir. Burada user, onu okuyan tek bileşen olan Avatar'a ulaşmak için App'ten Page ve Sidebar üzerinden yolculuk eder.

Dört seviye ve yalnızca sonuncusu user ile ilgileniyor. Console, Page ve Sidebar'ın hiç göstermedikleri bir değer için çalıştığını gösterir. Düğmeye tıkla; yeniden kayıt yazarlar.

Neden zarar verir

İki üç seviye sorun değil. Ağaç büyüdükçe prop drilling bir sorun hâline gelir:

  • Ortadaki bileşenler kullanmadıkları props'u taşır. Page ve Sidebar'ın imzasında artık bir user prop'u var, bu yüzden onları ne işe yaradığını merak etmeden okuyamazsın.
  • Her değişiklik her katmana dokunur. user.avatarUrl ya da onLogout gibi ikinci bir değer ekle; yalnızca iki ucu değil, yoldaki her bileşeni düzenlersin.
  • Bir bileşeni taşımak zinciri koparır. Avatar'ı farklı bir dala taşı; user'ı yeni bir yoldan geçirmen gerekir.
  • Bir prop'u düşürmek kolaydır. Bir katmanda onu iletmeyi unut; derindeki bileşen undefined alır ve onu kaybeden katmanda hiçbir hata olmaz.

Dene: App'e Avatar'ın çağırması gereken bir onLogout fonksiyonu ekle. Dört bileşenin hepsini düzenleyeceksin.

Çözüm 1: children ile composition

İnsanların atladığı çözüm budur. Derindeki bir bileşen onunla render edebilsin diye veriyi aşağı aktarmak yerine, verinin sahibi olan bileşenin derindeki bileşeni kendisinin render etmesine izin ver ve bitmiş öğeyi children (ya da başka bir prop) olarak aşağı aktar. Ortadaki katmanlar bir yuva render eder ve user'ı hiç görmez.

Page ve Sidebar artık bir kullanıcının var olduğunu bilmiyor. App, Avatar'ı user'ın yaşadığı yerde oluşturur ve hazır bir öğe olarak aşağı verir. Bunlar gibi yerleşim bileşenleri yeniden kullanılabilir hâle gelir ve onLogout eklemek artık yalnızca App ile Avatar'da bir değişikliktir. İkisi de hâlâ her tıklamada kayıt yazar, çünkü App her render olduğunda onlara yeni bir öğe aktarır: composition kodu sadeleştirir, render sayısını değil. children sayfası daha fazla yuva kalıbını anlatıyor.

Composition, verinin sahibi olan bileşen derindeki parçanın nasıl görüneceğine de karar verebildiğinde çalışır. Derindeki bileşen sahibinin render etmediği bir kütüphanenin ya da yapının içinde durduğunda yardımcı olmaz.

Çözüm 2: context

Farklı derinliklerdeki birçok bileşenin aynı değere (tema, oturum açmış kullanıcı, mevcut dil) ihtiyacı olduğunda onu context'e koy. Provider'ın altındaki her bileşen onu useContext ile okur ve aradaki hiçbir şey değişmez.

Avatar ve Greeting kullanıcıyı iki farklı derinlikten okur, Page ve Sidebar ise hiç props almaz. Page'in altında herhangi bir yere üçüncü bir okuyucu ekle; gerisine dokunmadan çalışır. Maliyeti: veri akışı artık props'ta görünmez ve değer değiştiğinde her okuyucu render olur. useContext sayfası provider'ları, varsayılanları ve bu yeniden render'ları anlatıyor.

Çözüm 3: bir state kütüphanesi

Birçok bileşenin okuduğu ve sık değişen büyük uygulama state'i için (bir sepet, bir belge editörü, canlı veri) Redux Toolkit, Zustand ya da Jotai gibi bir state kütüphanesi her bileşenin yalnızca kullandığı parçaya abone olmasını sağlar. Bu hem drilling'i hem de tek büyük bir context'in "her tüketici render olur" maliyetini önler. Aynı zamanda başka bir bağımlılık ve başka bir kavram setidir, bu yüzden ona üç seviye yolculuk eden bir prop'u düzeltmek için değil, ilk iki çözüm yetmez olduğunda başvur.

// Zustand, for comparison (not available in the editor here)
const useCart = create((set) => ({
    items: [],
    add: (item) => set((s) => ({ items: [...s.items, item] })),
}));

function CartCount() {
    const count = useCart((s) => s.items.length); // renders only when the count changes
    return <span>{count}</span>;
}

Prop drilling ne zaman sorun değildir

Props aktarmak React'te verinin akış biçimidir ve okunması en kolay kalıptır: bir değeri JSX'e bakarak en üstten en alta kadar izleyebilirsin. Bir kısmını kullanan bir iki bileşenden ya da birbiriyle yakından ilişkili bileşenlerden oluşan kısa bir zincirden geçen bir prop çözülmesi gereken bir sorun değildir. State'i en yakın ortak ebeveyne taşı, aşağı aktar ve yaklaşımını yalnızca ortadaki katmanlar hiçbir işe yaramayan props taşımaya başladığında değiştir.

Sıkça Sorulan Sorular

React'te prop drilling nedir?

Bir prop'u, yalnızca ağacın derinlerindeki bir bileşen okuyabilsin diye onu kullanmayan birkaç bileşen katmanından aşağı aktarmak. Ortadaki her bileşen prop'u kabul eder ve iletir.

Prop drilling kötü mü?

Kendi başına değil. Bir değeri iki üç seviye aşağı aktarmak açıktır ve takip etmesi kolaydır. Birçok katman hiç kullanmadığı props'u taşıdığında sorun olur; o zaman her yeniden adlandırma ya da yeni alan onunla hiçbir ilgisi olmayan dosyalara dokunur.

Prop drilling nasıl önlenir?

Önce composition'ı dene: derindeki bileşeni ebeveynin oluşturmasına izin ver ve onu children ya da başka bir prop olarak aşağı aktar, böylece ortadaki katmanlar veriyi hiç görmez. Farklı derinliklerdeki birçok bileşenin değere ihtiyacı varsa context kullan. Sık değişen büyük state için bir state kütüphanesini düşün.

Prop drilling'in tek çözümü context mi?

Hayır ve çoğu zaman en iyisi de değil. children ile composition, bir context eklemeden drilling'i ortadan kaldırır ve veri akışını kodda görünür tutar.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA