React एप्लिकेशन कंपोनेंट्स से बने होते हैं, और हर कंपोनेंट का अपना एक जीवन होता है। यह स्क्रीन पर दिखाई देता है। यह नई जानकारी पर प्रतिक्रिया देता है। अंततः यह गायब हो जाता है। इस लय (rhythm) को नज़रअंदाज़ करने की कीमत चुकानी पड़ती है। मेमोरी लीक (memory leaks) होने लगते हैं। रेंडर परफॉरमेंस (render performance) कम होने लगती है। यूज़र्स उन बटनों पर क्लिक करते हैं जो अब काम नहीं करते क्योंकि उनसे जुड़ा कंपोनेंट दस मिनट पहले ही अनमाउंट (unmount) हो चुका था, लेकिन इवेंट लिसनर (event listener) अभी भी सक्रिय है। कंपोनेंट लाइफसाइकिल (component lifecycle) को समझना केवल एक अकादमिक अभ्यास नहीं है। यह ऐसा सॉफ़्टवेयर लिखने की नींव है जो वास्तविक उपयोग के दौरान विश्वसनीय बना रहे।
एक कंपोनेंट के अस्तित्व को तीन चरणों में सोचें। डेवलपर्स अक्सर इन्हें जन्म, विकास और मृत्यु के रूप में वर्णित करते हैं। React इन्हें mounting, updating, और unmounting कहता है। प्रत्येक चरण का एक विशिष्ट कार्य होता है, और प्रत्येक आपको कोड चलाने या उसे साफ़ (clean up) करने का एक सटीक क्षण देता है।
तीन चरण
Mounting जन्म है। कंपोनेंट बनाया जाता है और पहली बार ब्राउज़र DOM में डाला जाता है। यह आपका सेटअप विंडो है। यदि कंपोनेंट को रिमोट डेटा की आवश्यकता है, तो यह वही समय है जब आप उसे रिक्वेस्ट करते हैं। यदि इसे props से गणना किए गए शुरुआती state की आवश्यकता है, तो आप उसे यहाँ करते हैं। क्लास कंपोनेंट के युग में, यह componentDidMount का क्षेत्र था। आधुनिक फंक्शनल कंपोनेंट्स के साथ, आप इसे useEffect और एक खाली डिपेंडेंसी ऐरे (empty dependency array) के साथ संभालते हैं। मुख्य विवरण यह है कि कोड का यह ब्लॉक एक बार चलता है, ठीक उसके बाद जब React एलिमेंट को पेज में रखता है। यह यूजर प्रोफाइल फ़ेच करने या localStorage से कोई वैल्यू पढ़ने जैसे एक बार के सेटअप के लिए आदर्श बनाता है।
Updating विकास है। एक माउंटेड कंपोनेंट स्थिर नहीं रहता। पैरेंट (parent) से props आते हैं। यूज़र इंटरैक्शन से state बदलती है। पैरेंट खुद भी री-रेंडर (re-render) होता है, जिससे चाइल्ड (child) को भी उसका अनुसरण करना पड़ता है। React फिर UI को आपके डेटा के साथ सिंक (sync) रखने के लिए कंपोनेंट को री-रेंडर करता है। यह चरण कंपोनेंट के जीवन के दौरान कई बार दोहराया जाता है। हर बार जब कोई डिपेंडेंसी बदलती है, तो आपके इफेक्ट्स (effects) फिर से चलते हैं, और कंपोनेंट DOM में नया आउटपुट वापस भेजता है। क्योंकि यह चरण इतनी बार ट्रिगर होता है, इसलिए यहीं से अधिकांश परफॉरमेंस की समस्याएँ भी शुरू होती हैं। यहाँ होने वाला अनावश्यक काम तेज़ी से बढ़ता जाता है।
Unmounting मृत्यु है। कंपोनेंट स्क्रीन से हट जाता है, शायद इसलिए क्योंकि यूज़र किसी दूसरे पेज पर चला गया या किसी कंडीशनल रेंडर (conditional render) ने उसे बंद कर दिया। इस बिंदु पर, कंपोनेंट नष्ट हो जाता है, लेकिन बाहरी दुनिया को हमेशा इसका पता नहीं चलता। टाइमर चलते रहते हैं। WebSockets सुनते रहते हैं। window ऑब्जेक्ट पर इवेंट लिसनर जुड़े रहते हैं। यदि आप इन्हें साफ़ नहीं करते हैं, तो वे मृत कंपोनेंट्स के रेफरेंस (references) को थामे रखते हैं और मेमोरी लीक करते हैं। ब्राउज़र उन 'भूतों' (ghosts) पर प्रोसेसिंग पावर बर्बाद करता है। React आपको एक क्लीनअप फ़ंक्शन (cleanup function) ठीक इसलिए देता है ताकि आप कंपोनेंट के पूरी तरह गायब होने से पहले इंटरवल (intervals) को रोक सकें, कनेक्शन बंद कर सकें और लिसनर्स को हटा सकें।
क्लास मेथड्स से हुक्स (Hooks) तक
सालों तक, React इंजीनियरों ने क्लास कंपोनेंट्स के माध्यम से इन चरणों को मैनेज किया। लॉजिक अलग-अलग मेथड्स में बँटा हुआ था। आप componentDidMount के अंदर डेटा फ़ेच करते थे, componentDidUpdate के अंदर prop परिवर्तनों पर प्रतिक्रिया देते थे, और componentWillUnmount के अंदर सफाई करते थे। समस्या यह थी कि संबंधित लॉजिक बिखरा हुआ हो जाता था। एक एकल फीचर, जैसे कि लाइव चैट कनेक्शन, को केवल कनेक्ट करने, थ्रेड परिवर्तनों की जाँच करने और डिस्कनेक्ट करने के लिए तीन अलग-अलग लाइफसाइकिल मेथड्स में कोड की आवश्यकता होती थी।
हुक्स ने इसे बदल दिया। फंक्शनल कंपोनेंट्स में useEffect हुक आपको लॉजिक को लाइफसाइकिल चरण के बजाय उद्देश्य के आधार पर ग्रुप करने की अनुमति देता है। फिर भी, यदि आप जानते हैं कि कहाँ देखना है, तो मेंटल मॉडल (mental model) स्पष्ट रूप से मैप करता है।
माउंटिंग को संभालने के लिए, useEffect(() => { ... }, []) लिखें। खाली डिपेंडेंसी ऐरे React को बताता है कि इस इफेक्ट की कोई बाहरी डिपेंडेंसी नहीं है, इसलिए यह केवल शुरुआती रेंडर के बाद चलता है। यह componentDidMount की जगह लेता है।
अपडेट्स को संभालने के लिए, उन विशिष्ट वैल्यूज़ को शामिल करें जिन पर React नज़र रखे: useEffect(() => { ... }, [dependency])। जब रेंडर्स के बीच dependency बदलती है,
