जानें कि Fiber कैसे tree को reconcile करता है, updates को batch करता है, और rendering के काम को बीच में रोका जा सकने योग्य बनाता है।
इस पाठ को Kodokon में खोलेंReact 16 से, आंतरिक इंजन को Fiber कहा जाता है: आपके tree का हर element एक fiber node द्वारा दर्शाया जाता है, जो काम की एक इकाई है। React असल में दो trees बनाए रखता है (एक double-buffering तकनीक): current tree, जो स्क्रीन पर जो है उसे दर्शाता है, और workInProgress tree, जो rendering के दौरान बनाया जाता है। काम दो अलग-अलग चरणों में होता है: render phase (आपके components को call करना, अंतर की गणना करना), जो बीच में रोका जा सकने योग्य और दोबारा चलाए जा सकने योग्य है, फिर commit phase (DOM पर बदलाव लागू करना, effects चलाना), जो हमेशा synchronous और बीच में न रोका जा सकने योग्य होता है। Reconciliation दो heuristics पर निर्भर करता है जो तुलना की लागत को linear तक ले आते हैं: अगर किसी दिए गए स्थान पर element का type बदलता है, तो React पूरे subtree को नष्ट कर देता है और उसे फिर से बनाता है, state सहित; lists के लिए, key prop React को दो renders के बीच elements का मिलान करने देता है।
function List({ items }) {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<input defaultValue={item.label} />
</li>
))}
</ul>
);
}
// With key={index}, deleting the first item
// would shift the content of the remaining inputs.दूसरा मूलभूत तंत्र: batching। जब एक ही context के भीतर कई state updates ट्रिगर होते हैं, तो React उन्हें एकल render में समूहित कर देता है। React 18 से पहले, यह समूहन केवल React event handlers के भीतर ही काम करता था; createRoot के बाद से, यह हर जगह अपने आप होता है: timers, promises, native listeners। यही कारण है कि setState के तुरंत बाद state पढ़ने पर पुराना मान मिलता है: update शेड्यूल किया जाता है, लागू नहीं किया जाता।
function handleTick() {
setCount((c) => c + 1);
setFlag((f) => !f);
// React 18: a single render, even here.
}
setTimeout(handleTick, 100);
// Before React 18, this timer would trigger
// two successive renders.Concurrent rendering तर्क को और आगे ले जाता है: render phase को बीच में रोका, फिर से शुरू किया, या यहाँ तक कि छोड़कर दोबारा शुरू किया जा सकता है, अगर कोई अधिक ज़रूरी update आ जाए। React updates को प्राथमिकता के अनुसार क्रमबद्ध करता है (lanes): एक keystroke ज़रूरी है, startTransition से चिह्नित एक list filter नहीं। इसका सीधा परिणाम: आपके component functions शुद्ध (pure) होने चाहिए, क्योंकि React उन्हें बिना परिणाम commit किए कई बार call कर सकता है। एक और edge case: बीच में रोके जा सकने योग्य render के दौरान पढ़ा गया कोई external store (Redux, Zustand, कोई घर का बना singleton) render के बीच में बदल सकता है, जिससे एक असंगत interface बनता है जिसे tearing कहते हैं। useSyncExternalStore API इस समस्या को store बदलने पर एक synchronous render को मजबूर करके हल करता है।
import { useSyncExternalStore } from 'react';
function useWindowWidth() {
return useSyncExternalStore(
(notify) => {
window.addEventListener('resize', notify);
return () =>
window.removeEventListener('resize', notify);
},
() => window.innerWidth
);
}<div> element उसी स्थान पर <span> बन जाता है तो React क्या करता है?createRoot के साथ, किसी setTimeout के भीतर दो setState calls कितने renders ट्रिगर करती हैं?