— React — 9 min read
React, kullanıcı arayüzleri geliştirebileceğiniz bir JavaScript kütüphanesidir.
İçinde, bileşenlerin state değişikliklerini takip eden ve değişen kısımları güncelleyen bir mekanizma vardır.
React'ta bu işlem reconciliation (uyumlaştırma) olarak adlandırılır.
setState
metodunu çağırdığımızda React, state veya prop'ların değişip değişmediğini kontrol edip, değişen kısımlar varsa bu kısımları yeniden render eder.
Reconcilation hakkında yüksek seviyede genel bir bilgi için, React dokümanındaki uyumlaştırma bölümünü okuyabilirsiniz.
render
metodu çağırıldıktan sonra, elimize React elemanlarından oluşan bir ağaç geçer.
Bu react elemanları ağacının yanı sıra, React'ın state'i korumak için bir iç nesne ağacı (bileşenler, DOM düğümleri, vb.) vardır.
Versiyon 16'dan itibaren, React bu iç nesne ağacının yeni bir gerçekleştirimine geçti ve bunu yöneten algoritmanın kod adı Fiber'dir.
Bu yazıdaki anlattıklarım React'ı kullanmak için gerekli değildir. Ancak React'ın nasıl çalıştığını anlamak, React kullanırken yazdığınız kodun mantığını daha iyi kavramanızı sağlayabilir. Ayrıca, React'ın karmaşık problemler için uyguladığı çözümleri görmek de bakış açınızı genişletebilir. Ek olarak, React'a katkıda bulunmak gibi bir amacınız varsa, bu yazı size güzel bir kaynak olacaktır.
Yazının devamında aşağıdaki basit bileşen üzerinden konuşacağız:
class ClickCounter extends React.Component {constructor(props) {super(props);this.state = {count: 0};this.handleClick = this.handleClick.bind(this);}handleClick() {this.setState((state) => {return {count: state.count + 1};});}render() {return [<button key="1" onClick={this.handleClick}>Update counter</button>,<span key="2" style={{ color: 'black' }}>{this.state.count}</span>]}}render(<ClickCounter />);
Bu bileşen canlı olarak render edilmekte. İsterseniz kurcalayabilirisiniz.
React'taki her bileşenin, render metodundan döndürülen bir görünümü veya şablonu diyebileceğimiz bir kullanıcı arayüzü temsili vardır. İşte örnek bileşenimizin şablonu:
1<button key="1" onClick={this.onClick}>Update counter</button>2<span key="2" style={{ color: 'black' }}>{this.state.count}</span>
Bir şablon JSX derleyicisinden geçtiğinde, elimizde bir gurup React elemanı olur. JSX kullanmamız zorunlu olmadığından, örnek bileşenimiz için render metodunu şu şekilde yeniden yazabiliriz:
1render() {2 return [3 React.createElement(4 'button',5 {6 key: '1',7 onClick: this.onClick8 },9 'Update counter'10 ),11 React.createElement(12 'span',13 {14 key: '2',15 style: { color: 'black' }16 },17 this.state.count18 )19 ]20}
React.createElement
fonksiyonu çalıştıktan sonra render metodunun içi şu şekilde olacaktır:
1[2 {3 $$typeof: Symbol(react.element),4 type: 'button',5 key: "1",6 props: {7 children: 'Update counter',8 onClick: () => { ... }9 }10 },11 {12 $$typeof: Symbol(react.element),13 type: 'span',14 key: "2",15 props: {16 children: 0,17 style: { color: 'black' }18 }19 }20]
React'ın bu nesnelere
$$typeof
özelliğini eklediğini görebilirsiniz. Genel olarak, bunun güvenlik için eklendiğini söyleyebilirim.$$typeof
özelliği hakkında daha detaylı bilgiye buradan ulaşabilirsiniz.
type
, key
ve props
özellikleri React.createElement
fonksiyonuna geçtiğimiz parametrelerden geliyor.
Tüm haline buradan bakabilirsiniz.
ref
gibi özellikler konumuzun dışında olduğu için atlıyorum.
ClickCounter
bileşenimizin React elemanında herhangi bir state veya prop yoktur:
1{2 $$typeof: Symbol(react.element),3 key: null,4 props: {},5 type: ClickCounter6}
Reconciliation sırasında render metodundan döndürülen her React elemanının verisi, fiber ağacıyla birleştirilir. Her React elemanına karşılık gelen bir fiber düğümü vardır. React elemanlarından farklı olarak, fiberler her render işleminde yeniden oluşturulmaz. Bunlar, bileşenlerin state'ini ve DOM'u tutan değiştirilebilir veri yapılarıdır.
React elemanının türüne bağlı olarak, farklı aktiviteler gerçekleştirilir.
Örneğimizde, sınıf bileşeni ClickCounter
için yaşam döngüsü metodları ve render metodu çağırılırken, span
host bileşeni (DOM düğümü) için DOM mutasyonu gerçekleştirir.
Bundan dolayı her bir React elemanı, yapılması gereken işi tanımlayan ilgili tipte bir Fiber düğümüne dönüştürülür.
Fiber'i, yapılması gereken iş birimini temsil eden bir veri yapısı olarak düşünebilirsiniz.
Fiber’in mimarisi ayrıca yapılacak işi izlemek, planlamak, duraklatmak ve iptal etmek için uygun bir yol sağlar.
Bir React elemanı ilk kez bir fiber düğüme dönüştürülürken,
fiber düğümü oluşturmak için elemanın verileri kullanılarak createFiberFromTypeAndProps
fonksiyonu çağırılır.
Sonraki güncellemelerde, fiber düğümü sadece ona karşılık gelen React elemanının verisi kullanılarak gerekli özellikleri güncellenir.
Ayrıca, key
prop'una göre düğüm taşınır veya karşılık gelen React öğesi artık render metodundan döndürülmezse silinir.
React'ın mevcut fiber düğümleri için gerçekleştirdiği tüm etkinlikleri ve ilgili işlevleri görmek için
ChildReconciler
fonksiyonunu inceleyebilirsiniz.
Örneğimiz için, fiber ağacı şu şekilde görünür:
Tüm fiber düğümler, fiber düğümlerdeki şu özellikler kullanılarak bir linked list aracılığıyla bağlanır: child
, sibling
ve return (parent)
.
Fiber'in neden linked list kullandığı hakkında güzel bir yazıya şuradan ulaşabilirsiniz: The how and why on React’s usage of linked list in Fiber to walk the component’s tree
İlk render işleminden sonra React, kullanıcı arayüzünü oluşturmak için kullanılan ve uygulamanın durumunu yansıtan bir Fiber ağacı oluşturur. Bu ağaca genellikle current (şu anki) denir. React güncellemeler üzerinde çalışmaya başladığında, ekranın gelecekteki durumunu yansıtan bir workInProgress (yapım aşamasında) ağacı oluşturur.
Tüm çalışma workInProgress
ağacındaki fiberler üzerinde gerçekleştirilir.
React, current
ağacında gezinirken, mevcut her bir fiber düğümü için workInProgress
ağacını oluşturan alternatif bir düğüm oluşturur.
Bu düğüm, render metodu tarafından döndürülen React elemanından alınan veriler kullanılarak oluşturulur.
Güncellemeler işlendikten ve ilgili tüm çalışmalar tamamlandıktan sonra, React'in ekrana aktarılmaya hazır bir alternatif ağacı olacaktır.
Bu ağaç (workInProgress
) ekrana geçirildikten sonra, current
ağaç olur.
React’in temel ilkelerinden biri tutarlılıktır.
React, DOM'u her zaman tek seferde günceller ve kısmi sonuçlar göstermez.
workInProgress
ağacı, kullanıcı tarafından görülmeyen bir "taslak" görevi görür,
böylece React önce tüm bileşenleri işleyebilir ve ardından değişiklikleri ekrana aktarabilir.
Kaynak kodların içinde, hem current
hem de workInProgress
ağaçlarından fiber düğümler alan birçok fonksiyon görebilirsiniz.
İşte böyle bir fonksiyonun prototipi:
1function updateHostComponent(current, workInProgress, renderExpirationTime) {...}
Her bir fiber düğümü, diğer ağaçtan bir muadiline alternate (alternatif) alanında bir referans tutar.
current
ağaçtaki bir düğüm, workInProgress
ağacındaki düğüme işaret eder ve bunun tersi de geçerlidir.
Şimdi ClickCounter
bileşeni ve span
için oluşturulan fiber düğümlerin yapısına bakalım:
1{2 stateNode: new ClickCounter,3 type: ClickCounter,4 alternate: new FiberNode, /* tag: 1, stateNode: new ClickCounter */5 key: null,6 updateQueue: null,7 memoizedState: {count: 0},8 pendingProps: {},9 memoizedProps: {},10 tag: 1,11 effectTag: 0,12 nextEffect: null,13 return: new FiberNode, /* tag: 8, stateNode: null */14 child: new FiberNode, /* tag: 5, stateNode: button */15 sibling: null16}
1{2 stateNode: new HTMLSpanElement,3 type: "span",4 alternate: new FiberNode, /* tag: 5, stateNode: "span" */5 key: "2",6 updateQueue: null,7 memoizedState: null,8 pendingProps: {children: 0},9 memoizedProps: {children: 0},10 tag: 5,11 effectTag: 0,12 nextEffect: null,13 return: new FiberNode, /* tag: 1, stateNode: ClickCounter */14 child: null,15 sibling: null,16}
Halihazırda oluşmuş neseneleri temsil etmek için
new ClassName
kalıbını kullandığıma dikkat edin.
Fiber düğümlerde oldukça fazla alan var.
Önceki bölümlerde alternate
alanlanının amacını açıkladım.
Bir sonraki bölümde de, effectTag
ve nextEffect
alanlarını açıklayacağım.
Şimdi, neden diğerlerine ihtiyacımız olduğunu görelim.
Fiber düğümle ilişkilendirilmiş bir bileşenin, bir DOM düğümünün veya diğer React elemanı tipinin sınıf nesnesine ait referansı tutar. Genel olarak, bu özelliğin bir fiberle ilişkili yerel state'i tutmak için kullanıldığını söyleyebiliriz.
Bu fiber ile ilişkili fonksiyonu veya sınıfı tanımlar. Sınıf bileşenleri için yapıcı fonksiyona (constructor) işaret eder ve DOM öğeleri için HTML etiketini belirtir.
Fiber tipini tanımlar.
Reconciliation algoritmasında hangi işin yapılması gerektiğini belirlemek için kullanılır.
Örneğimizde, ClickCounter
bileşeninin tipi ClassComponent (1)
ve span
öğesininki HostComponent (5)
dir.
State güncellemeleri, callbackler ve DOM güncellemelerinden oluşan bir kuyruk.
Çıktıyı oluşturmak için kullanılan fiberin state'i. Güncellemeleri işlerken, o anda ekranda oluşturulmakta olan state'i yansıtır.
Önceki render sırasında çıktıyı oluşturmak için kullanılan fiberin prop'ları.
React elemanlarındaki yeni verilerle güncellenen ve alt bileşenlere veya DOM öğelerine uygulanması gereken prop'lar.
React'in bir grup çocuk içinden hangi öğelerin değiştiğini, listeye eklendiğini veya listeden kaldırıldığını anlamanıza yardımcı olacak benzersiz bir tanımlayıcı. Key hakkında daha fazla bilgi için dokümandaki Listeler ve Anahtarlar kısmına bakabilirsiniz.
React'ın reconciliation sırasında, fiber düğümler arasında dolaşmasını sağlar. Aşağıda algoritmayı açıklarken daha net bir şekilde üzerlerinden geçeceğiz.
Fiber düğümün tüm yapısına buradan bulabilirsiniz. Konumuzun dışında olan Scheduler'e özgü
expirationTime
,childExpirationTime
vemode
gibi alanları es geçtiğimi görebilirsiniz.
Bir fiber düğüm'e ulaşmak için Chrome'da aşağıdaki işlemi uygulayabilirisiniz (keşif ve dubug için):
React'taki bir bileşeni, kullanıcı arayüzünün temsilini hesaplamak için state ve prop'ları kullanan bir fonksiyon olarak düşünebiliriz. DOM'u mutasyona geçirmek veya yaşam döngüsü yöntemlerini çağırmak gibi diğer tüm işlemler bir yan etki (side-effect) veya basitçe bir etki (effect) olarak düşünülmelidir.
Çoğu state ve prop güncellemesinin yan etkilere nasıl yol açtığını görebilirsiniz.
Ve etki uygulamak/işlemek bir tür iş olduğundan, bir fiber düğüm, güncellemelere ek olarak etkileri izlemek için uygun bir mekanizmadır.
Her fiber düğümün kendisiyle ilişkili etkileri olabilir.
Bunlar, effectTag
alanına kodlanırlar.
Bu nedenle, Fiber'deki etkiler temel olarak güncellemeler işlendikten sonra
yapılması gereken işleri tanımlar.
DOM öğeleri için iş, öğe ekleme, güncelleme veya kaldırma işlemlerinden oluşur.
Sınıf bileşenleri için React'in ref
'leri güncellemesi ve componentDidMount
ve componentDidUpdate
yaşam döngüsü yöntemlerini çağırması gerekebilir.
Diğer fiber türlerine karşılık gelen başka etkiler de vardır.
React, güncellemeleri çok hızlı bir şekilde işler ve bu performans seviyesine ulaşmak için birkaç ilginç teknik kullanır. Bunlardan biri, hızlı iterasyon için etkilere sahip olan doğrusal bir fiber düğüm listesi oluşturmasıdır. Doğrusal listede gezinmek bir ağaçtan çok daha hızlıdır ve yan etkileri olmayan düğümlerde zaman geçirmeye de gerek yoktur.
Bu listenin amacı, DOM güncellemelerine veya bunlarla ilişkili diğer etkilere sahip düğümleri işaretlemektir.
Bu liste finishedWork
ağacının bir alt kümesidir ve current
ve workInProgress
ağaçlarında kullanılan child
özelliği yerine nextEffect
özelliğini kullanarak diğer düğümlere bağlanır.
React, reconciliation (uyumlaştırma) işini iki ana aşamada gerçekleştirir: render
ve commit
.
İlk olarak, render
aşamasında React, setState
veya React.render
aracılığıyla bileşenlere güncellemeler uygular ve kullanıcı arayüzünde nelerin güncellenmesi gerektiğini bulur.
Eğer ilk render
işlemi ise React, render metodundan döndürülen her öğe için yeni bir fiber düğümü oluşturur.
Sonraki güncellemelerde, mevcut React elemanları için fiberler yeniden kullanılır ve güncellenir.
Bu işlemin sonucu, yan etkilerle (side-effects) işaretlenmiş bir fiber düğüm ağacıdır.
Etkiler, bir sonraki commit
aşamasında yapılması gereken işi açıklar.
Bu aşamada React, etkilerle işaretlenmiş bir fiber ağacı alır ve bunları nesnelere uygular.
Etkiler listesini gözden geçirir ve DOM güncellemelerini ve kullanıcı tarafından görülebilen diğer değişiklikleri gerçekleştirir.
render
aşamasında çalışmanın eşzamansız olarak gerçekleştirilebileceğini anlamak önemlidir.
React, mevcut zamana bağlı olarak bir veya daha fazla fiber düğümü işleyebilir, daha sonra yapılan işi tutmak ve bir olaya izin vermek (kullanıcı'nın parola yazması gibi) için durabilir.
Daha sonra kaldığı yerden devam eder.
Bazen de, yapılan işten kurtulup tekrar üstten başlaması gerekebilir.
Bu duraklamalar, gerçekleştirilen çalışmanın DOM güncellemeleri gibi kullanıcı tarafından görülebilir değişikliklere yol açmadığı için mümkün olur.
Buna karşılık, commit
aşaması her zaman eşzamanlıdır.
Bunun nedeni, bu aşama sırasında yapılan çalışmanın kullanıcı tarafından görülebilir değişikliklere (DOM güncellemeleri gib) yol açmasıdır.
React'ın bunu tek bir seferde yapmasının nedeni budur.
Yaşam döngüsü (lifecycle) metodlarını çağırmak, React tarafından gerçekleştirilen bir çalışma türüdür.
Bazı metodlar render
aşamasında, diğerleri ise commit
aşamasında çağrılır.
render
aşamasında çalışırken çağrılan yaşam döngülerinin listesi:
getDerivedStateFromProps
shouldComponentUpdate
render
componentWillMount
,componentWillReceiveProps
,componentWillUpdate
metodları kullanımdan kaldırıldı. Bunun nedeni,render
aşaması DOM güncellemeleri gibi yan etkiler üretmediğinden, React güncellemeleri bileşenlerle eşzamansız bir şekilde eşzamanlı olarak işleyebilir. "Bu metodlar yerine ne kullanmalıyız?" diyorsanız Update on Async Rendering yazsına göz atmak isteyebilirsiniz.
commit
aşamasında çağırılan yaşam döngüsü metodlarının listesi:
getSnapshotBeforeUpdate
componentDidMount
componentDidUpdate
componentWillUnmount
Bu yöntemler eşzamanlı commit
aşamasında yürütüldüğünden, yan etkiler içerebilir ve DOM'a dokunabilirler.
Şimdi ağaçta gezinmek ve iş yapmak için kullanılan genel algoritmaya göz atmak için arka planımız var. Hemen başlayalım.
React'ın kalbinin attığı yer burasıdır diyebiliriz. Teknik kısma girmeden önce, sözde kod olarak algoritmanın nasıl gezindiğini tanımlayalım:
Aşağıdaki örnek ağacı ele alalım:
Bu örnekte gezme sırası (ilk gelme sırasına göre) şu şekide olacaktır:
A -> B -> C -> E -> G -> H -> D -> F
Reconciliation algoritması, renderRoot fonksiyonunu kullanarak her zaman en üstteki HostRoot
fiber düğümünden başlar.
Bununla birlikte React, tamamlanmış düğümleri hızlıca atlayarak işlenmemiş fiber düğümlere geçer.
Tüm fiber düğümler workLoop içinde işlenir. Döngünün senkron bölümünün uygulaması:
1function workLoop(isYieldy) {2 if (!isYieldy) {3 while (nextUnitOfWork !== null) {4 nextUnitOfWork = performUnitOfWork(nextUnitOfWork);5 }6 } else {...}7}
Yukarıdaki kodda nextUnitOfWork
, yapılması gereken iş olarak workInProgress
ağacından bir fiber düğüme referans tutar.
React, fiber ağacında dolaştıkça, bu değişkeni, bitmemiş işi olan başka bir fiber düğüm olup olmadığını bilmek için kullanır.
Mevcut fiber işlendikten sonra değişken, ağaçtaki bir sonraki fiber düğüme referans içerecek veya null
olacaktır.
null
durumunda React, iş döngüsünden çıkar ve değişiklikleri işlemeye (commit) hazır olur.
Ağaçta gezinmek ve işi başlatmak veya tamamlamak için kullanılan dört ana fonksiyon vardır:
İlk iki fonksiyon olan performUnitOfWork
ve beginWork
ile başlayalım:
1function performUnitOfWork(workInProgress) {2 let next = beginWork(workInProgress);3 if (next === null) {4 next = completeUnitOfWork(workInProgress);5 }6 return next;7}89function beginWork(workInProgress) {10 console.log('work performed for ' + workInProgress.name);11 return workInProgress.child;12}
performUnitOfWork
fonksiyonu, workInProgress
ağacından bir fiber düğüm alır ve beginWork
fonksiyonu çağırarak çalışmaya başlar.
Bu, bir fiber için yapılması gereken tüm aktiviteleri başlayacak olan fonksiyondur.
Bu yazının amaçları doğrultusunda, sadece işin yapıldığını belirtmek için fiberin adını console'a basıyoruz.
beginWork
fonksiyonu, döngüde işlemek için her zaman bir sonraki çocuğa referans veya null
döndürür.
Bir sonraki çocuk varsa, workLoop
için nextUnitOfWork
değişkenine atanacaktır.
Ancak çocuk yoksa React, dalın sonuna geldiğini bilir ve böylece geçerli düğümü tamamlayabilir.
Düğüm tamamlandığında, kardeşler için çalışması ve bundan sonra ebeveyne geri dönmesi gerekir.
Bu, completeUnitOfWork
fonksiyonunda yapılır:
1function completeUnitOfWork(workInProgress) {2 while (true) {3 let returnFiber = workInProgress.return;4 let siblingFiber = workInProgress.sibling;56 nextUnitOfWork = completeWork(workInProgress);78 if (siblingFiber !== null) {9 // Kardeş varsa, performUnitOfWork içinde çalıştırılması için döndür.10 return siblingFiber;11 } else if (returnFiber !== null) {12 // returnFiber'de başka iş yoksa, üst düğümü tamamlamak için döngüye devam et.13 workInProgress = returnFiber;14 continue;15 } else {16 // Kök'e ulaştık :)17 return null;18 }19 }20}2122function completeWork(workInProgress) {23 console.log('work completed for ' + workInProgress.name);24 return null;25}
Fonksiyonun özünün büyük bir while döngüsü olduğunu görebilirsiniz.
React, workInProgress
düğümüne ait bir çocuk olmadığında bu fonksiyona girer.
Mevcut fiber için çalışmayı tamamladıktan sonra, bir kardeş olup olmadığını kontrol eder.
Eğer kardeş bulunursa, React fonksiyondan çıkar ve o kardeşe ait referansı döndürür.
nextUnitOfWork
değişkenine atanacak ve React bu kardeşten başlayarak dal için çalışacaktır.
Bu noktada React'ın sadece önceki kardeşler için çalışmayı tamamladığını anlamak önemlidir.
Yalnızca alt düğümlerle başlayan tüm dallar tamamlandıktan sonra üst düğüm ve gerisi için işi tamamlanır.
Uygulamadan da görebileceğiniz gibi, hem performUnitOfWork
hem de completeUnitOfWork
çoğunlukla iterasyon amacıyla kullanılırken, ana faaliyetler beginWork
ve completeWork
fonksiyonlarında gerçekleşir.
Aşama, completeRoot
fonksiyonu ile başlar.
Burada React, DOM'u günceller ve mutasyon öncesi ve sonrası yaşam döngüsü yöntemlerini çağırır.
Kullandığım mutasyon kelimesi genel olarak, bir React elemanının geçirdiği/geçireceği değişimi ifade eder.
React bu aşamaya geldiğinde elinde iki ağaç ve etki listesi vardır.
İlk ağaç, ekranda görüntülenmekte olan durumu gösterir.
İkinci ağaç, render aşamasında oluşturulmuş olan alternatif ağaçtır.
Buna kaynak kodda finishedWork
veya workInProgress
adı verilir ve ekrana yansıtılması gereken durumu gösterir.
Bu alternatif ağaç, çocuk ve kardeş referansları aracılığıyla mevcut ağaca benzer şekilde bağlanır.
Etki listesi ise, finishedWork
ağacının nextEffect
işaretçisi ile bağlı olan fiberlerinden oluşan bir alt kümedir.
Etki listesinin, render
aşamasının bir sonucu olduğunu unutmayın.
render
aşamasının tüm amacı, hangi düğümlerin eklenmesi, güncellenmesi veya kaldırılması gerektiğini ve hangi bileşenlerin yaşam döngüsü yöntemlerinin çağrılması gerektiğini belirlemekti.
İşte etki listesi bize bunu söylüyor.
Ve ayrıca, bu tam olarak commit
aşamasında gezilen düğümler kümesidir.
commit
aşamasında çalışan ana fonksiyon, commitRoot
'tur.
Temel olarak, aşağıdakileri yapar:
Snapshot
etkisiyle etiketlenmiş düğümlerde getSnapshotBeforeUpdate
yaşam döngüsü metodunu çağırır.Deletion
etkisiyle ile etiketlenmiş düğümlerde componentWillUnmount
yaşam döngüsü metodunu çağırır.finishedWork
ağacını current
(şimdiki) ile değiştirir.Placement
etkisiyle etiketlenmiş düğümlerde componentDidMount
yaşam döngüsü metodunu çağırır.Update
etkisiyle ile etiketlenmiş düğümlerde componentDidUpdate
yaşam döngüsü metodunu çağırır.getSnapshotBeforeUpdate
ön mutasyon metodunu çağırdıktan sonra React, bir ağaçtaki tüm yan etkileri işler (commit).
Bunu iki adımda yapar.
İlk adımda, tüm DOM (host) ekleme, güncelleme, silme işlemlerini ve ref
bağlantılarını kaldırma işlemlerini gerçekleştirir.
Daha sonra React, finishedWork
ağacını, (workInProgress
ağacını current
ağaç olarak işaretleyerek) FiberRoot
'a atar.
Bu, commit aşamasının ilk adımından sonra yapılır, böylece bir önceki ağaç componentWillUnmount
sırasında hala geçerli olur,
ancak ikinci adımdan önce tamamlanır, böylece biten çalışma componentDidMount/Update
sırasında geçerli olur.
İkinci adımda React, diğer tüm yaşam döngüsü metodlarını ve ref
callbacklerini çağırır.
Bu metodlar ayrı bir adım olarak yürütülür, böylece ağaçtaki tüm yerleşimler, güncellemeler ve silme işlemleri zaten çağırılmış olur.
Yukarıda açıklanan adımları çalıştıran fonksiyonun özeti:
1function commitRoot(root, finishedWork) {2 commitBeforeMutationLifecycles()3 commitAllHostEffects();4 root.current = finishedWork;5 commitAllLifeCycles();6}
Bu alt fonksiyonlardan her biri, etkiler listesinde gezinen ve etkilerin türüne göre çalışan bir döngü uygular. Fonksiyonun amacına ilişkin bir etki bulduğunda, uygular.
Örneğin, bir etki ağacı üzerinde gezinen ve bir düğümün Snapshot
etkisine sahip olup olmadığını kontrol eden kod:
1function commitBeforeMutationLifecycles() {2 while (nextEffect !== null) {3 const effectTag = nextEffect.effectTag;4 if (effectTag & Snapshot) {5 const current = nextEffect.alternate;6 commitBeforeMutationLifeCycles(current, nextEffect);7 }8 nextEffect = nextEffect.nextEffect;9 }10}
Bir sınıf bileşeni için bu etki getSnapshotBeforeUpdate
yaşam döngüsü metodunu çağırmak anlamına gelir.
commitAllHostEffects
, React'in DOM güncellemelerini gerçekleştirdiği fonksiyondur.
Fonksiyon temel olarak bir düğüm için yapılması gereken işlem türünü tanımlar ve yürütür:
1function commitAllHostEffects() {2 switch (primaryEffectTag) {3 case Placement: {4 commitPlacement(nextEffect);5 ...6 }7 case PlacementAndUpdate: {8 commitPlacement(nextEffect);9 commitWork(current, nextEffect);10 ...11 }12 case Update: {13 commitWork(current, nextEffect);14 ...15 }16 case Deletion: {17 commitDeletion(nextEffect);18 ...19 }20 }21}
React'in,
commitDeletion
fonksiyonundaki silme işleminin bir parçası olarakcomponentWillUnmount
metodunu çağırması ilginçtir.
commitAllLifecycles,
React'ın kalan tüm yaşam döngüsü yöntemlerini (componentDidUpdate
ve componentDidMount
) çağırdığı fonksiyondur.
Buraya kadar geldiğiniz için teşekkürler. Umarım keyifli bir okuma olmuştur. Eğer ingilizceniz el veriyorsa, neredeyse bire bir gittiğim Inside Fiber: an in-depth overview of the new reconciliation algorithm in React yazısını da okumanızı öneririm. Kendinize iyi bakın.