Bardzo ciekawy post!
💥 Jak naprawdę działa React? React działa tak, że oprócz DOM tworzy VDOM, potem jak zachodzi zmiana tworzy drugi VDOM i porównuje zmiany stanu i na tej podstawie udpateuje drzewo DOM. Ten opis jest bardzo dużym uproszczeniem. Warto rozumieć jak to jest naprawdę. VDOM to pewien model, a nie implementacja! Ta nazywa i się Fiber tree jest dokładnie tym, drzewem składającym się z Fiberów. No ale by to zrozumieć warto wpierw wejść z fazy workflow Reacta. Działanie React dzieli się na kluczowe fazy, które mają podfazy: 1. Update 2. Batching 3. Scheduler 4. Render Phase 5. Commit Phase W fazie update powstaje jakaś aktualizacja stanu, która trafia do kolejki "udpate queue". Każdy elementa ma reprezentacje w React w formie Fibera no i każdy Fiber ma swoją updateQueue. Tam trafiają update’y mają przypisane lane z priorytetem. W Batchingu, udpate'y są składane w paczki. Jednostki pracy "batche" składane są pod ich execution context. Scheduler decyduje o kolejności ich wykonywania na podstawie całego obrazu sytuacji, korzystając z priorytetu zdefiniowanego przez priorytet "lane'ów". No i dopiero tutaj mamy render! :D Render jest globalny ,czyli React idzie sobie od roota. Dla tworzony jest "Work In Progress" Fiber, czyli jego kopia. Nie jest jednak ona tworzona cała na raz ale egzekucja odbywa się Fiber po Fiberze. Potem przetwarzając to WiP drzewo, React podejmuje następujące decyzje: Albo jeszcze inaczej. Dla każdego fibera wywoływane jest performUnitOfWork(fiber). W ramach niego: Fiber: ├─ bailout? → TAK → skip └─ bailout? → NIE ├─ UPDATE ├─ INSERT └─ DELETE Bailout to brak zmian -> pominięcie. No a potem przechodzi do dzieci i ponownie wykonuje ten sam zestaw akcji. Zbiera udapte'y z updateQueue i wylicza końcowy stan. Ocenia czy ma do zrobienia jeszcze jakąs pracę i jeśli nie zamyka pracę nad danym fiberem. Wtedy składa go do kupy razem z jego dziećmi tworząc tzw. detached DOM subtree. To jest element składowy tego co zostanie zacommitowne później. Macie tu pseudokod do wizualizacji: completeWork(fiber): 1. jeśli nowy element: create DOM node 2. jeśli update: prepare update payload 3. połącz dzieci (append) 4. uataw flags (Placement / Update / Deletion) 5. przekaż efekty do parenta Czyli WIP fibery zostają przeliczone już na strukturę detached DOM, która ostatecznie zostanie zacommitowana w końcowej fazie. 🤌 No i dopiero tutaj następuje COMMIT PHASE! Oczywiście ma też subfazy. Najpierw czytany jest obecny DOM i przygotowany na zmiany. (snapshot). Potem faze mutacji, gdzie zmiany są wprowadzane na podstawie tego co zostało oflagowane. No i fazę layoutu jako końcową. DOM został już zaktualizowany, ale użytkownik jeszcze go nie widzi. Layout już jest wyliczony, a my możemy na nim operować. Możemy tutaj operować useLayoutEffect. No i dopiero tutaj mamy PAINT -> przeglądarka rysuje nam piksele. Całość jest składana w Composite i trafia do usera. Jesli jest useEffect to odpala się dopiero teraz.