React ॲप्लिकेशन्स कंपोनंट्सपासून बनलेली असतात आणि प्रत्येक कंपोनंटचे स्वतःचे एक जीवन असते. तो स्क्रीनवर दिसतो. नवीन माहितीला तो प्रतिसाद देतो. शेवटी तो नाहीसा होतो. या लयीकडे दुर्लक्ष केल्यास त्याची मोठी किंमत मोजावी लागते. मेमरी लीक्स (Memory leaks) वाढू लागतात. रेंडर परफॉर्मन्स (Render performance) खालावतो. युजर्स अशा बटणांवर क्लिक करतात ज्यांना आता प्रतिसाद मिळत नाही, कारण त्यांच्याशी जोडलेला कंपोनंट दहा मिनिटांपूर्वी अनमाउंट (unmounted) झाला होता, पण इव्हेंट लिसनर (event listener) अजूनही जिवंत आहे. कंपोनंट लाइफसायकल (component lifecycle) समजून घेणे हा केवळ एक शैक्षणिक व्यायाम नाही. प्रत्यक्ष वापरामध्ये विश्वसनीय सॉफ्टवेअर लिहिण्यासाठी तो एक पाया आहे.

कंपोनंटच्या अस्तित्वाचा विचार तीन टप्प्यांत करा. डेव्हलपर्स अनेकदा त्यांचे वर्णन जन्म, वाढ आणि मृत्यू असे करतात. React ला ते माउंटिंग (mounting), अपडेटिंग (updating) आणि अनमाउंटिंग (unmounting) म्हणतात. प्रत्येक टप्प्याचे एक विशिष्ट काम असते आणि प्रत्येक टप्पा तुम्हाला कोड चालवण्यासाठी किंवा तो स्वच्छ (clean up) करण्यासाठी एक अचूक क्षण देतो.

तीन टप्पे

Mounting म्हणजे जन्म. कंपोनंट तयार केला जातो आणि पहिल्यांदा ब्राउझर DOM मध्ये समाविष्ट केला जातो. हा तुमचा सेटअपचा काळ असतो. जर कंपोनंटला रिमोट डेटाची गरज असेल, तर याच वेळी तुम्ही तो विनंती (request) करता. जर त्याला props मधून मोजलेला सुरुवातीचा स्टेट (initial state) हवा असेल, तर तुम्ही ते येथे करता. क्लास कंपोनंटच्या काळात, हे componentDidMount चे क्षेत्र होते. आधुनिक फंक्शनल कंपोनंट्समध्ये, तुम्ही useEffect आणि रिकाम्या डिपेंडन्सी ॲरे (empty dependency array) द्वारे ते हाताळता. महत्त्वाचा तपशील म्हणजे, React ने एलिमेंट पेजमध्ये ठेवल्याबरोबर हा कोड ब्लॉक एकदाच चालतो. यामुळे युजर प्रोफाइल मिळवणे किंवा localStorage मधून व्हॅल्यू वाचणे यांसारख्या वन-टाइम सेटअपसाठी हे आदर्श ठरते.

Updating म्हणजे वाढ. माउंट झालेला कंपोनंट स्थिर राहत नाही. पॅरेंटकडून (parent) props येतात. युजरच्या इंटरअॅक्शनमुळे स्टेट (state) बदलते. पॅरेंट स्वतः री-रेंडर (re-render) होतो, ज्यामुळे चाइल्डलाही तसे करावे लागते. त्यानंतर, UI तुमच्या डेटाशी सुसंगत ठेवण्यासाठी React कंपोनंटला पुन्हा रेंडर करते. कंपोनंटच्या आयुष्यात हा टप्पा अनेक वेळा येतो. प्रत्येक वेळी जेव्हा एखादी डिपेंडन्सी बदलते, तेव्हा तुमचे इफेक्ट्स (effects) पुन्हा चालतात आणि कंपोनंट DOM मध्ये नवीन आउटपुट पाठवतो. हा टप्पा वारंवार घडत असल्याने, बहुतेक परफॉर्मन्सच्या समस्या देखील येथूनच सुरू होतात. येथे होणारे अनावश्यक काम वेगाने वाढते.

Unmounting म्हणजे मृत्यू. कंपोनंट स्क्रीनवरून निघून जातो, कदाचित युजरने दुसऱ्या पेजवर नेव्हिगेट केल्यामुळे किंवा कंडिशनल रेंडर (conditional render) बंद झाल्यामुळे. या वेळी, कंपोनंट नष्ट होतो, पण बाहेरील जगाला ते नेहमीच कळत नाही. टाइमर्स (timers) चालूच राहतात. WebSockets ऐकतच राहतात. window ऑब्जेक्टवरील इव्हेंट लिसनर्स जोडलेलेच राहतात. जर तुम्ही हे स्वच्छ केले नाही, तर ते मृत कंपोनंट्सचे संदर्भ (references) धरून ठेवतात आणि मेमरी लीक करतात. ब्राउझर 'भूत' (ghosts) गोष्टींवर सायकल वाया घालवतो. कंपोनंट कायमचा नाहीसा होण्यापूर्वी तुम्ही इंटरव्हल्स थांबवू शकाल, कनेक्शन बंद करू शकाल आणि लिसनर्स काढून टाकू शकाल, यासाठी React तुम्हाला नेमकी एक 'क्लीनअप फंक्शन' (cleanup function) देते.

क्लास मेथड्सपासून हुक्सपर्यंत

अनेक वर्षे, React इंजिनिअर्सनी क्लास कंपोनंट्सद्वारे हे टप्पे व्यवस्थापित केले. लॉजिक वेगवेगळ्या मेथड्समध्ये विभागलेले होते. तुम्ही componentDidMount मध्ये डेटा मिळवत होता, componentDidUpdate मध्ये prop बदलांना प्रतिसाद देत होता आणि componentWillUnmount मध्ये स्वच्छता करत होता. समस्या अशी होती की संबंधित लॉजिक विखुरलेले असायचे. लाइव्ह चॅट कनेक्शनसारख्या एका फीचरसाठी, फक्त कनेक्ट होण्यासाठी, थ्रेडमधील बदल तपासण्यासाठी आणि डिस्कनेक्ट करण्यासाठी तीन वेगवेगळ्या लाइफसायकल मेथड्समध्ये कोड लिहावा लागायचा.

हुक्सनी (Hooks) हे बदलले. फंक्शनल कंपोनंट्समधील useEffect हुक तुम्हाला लाइफसायकल टप्प्यांऐवजी उद्देशानुसार लॉजिक एकत्र करण्याची परवानगी देतो. तरीही, तुम्हाला कुठे पाहायचे आहे हे माहित असल्यास, मेंटल मॉडेल (mental model) स्पष्टपणे मॅप होते.

माउंटिंग हाताळण्यासाठी, useEffect(() => { ... }, []) असे लिहा. रिकामी डिपेंडन्सी ॲरे React ला सांगते की या इफेक्टला कोणतेही बाह्य अवलंबित्व (external dependencies) नाही, त्यामुळे तो केवळ सुरुवातीच्या रेंडरनंतर चालतो. हे componentDidMount ची जागा घेते.

अपडेट्स हाताळण्यासाठी, React ने ज्या विशिष्ट व्हॅल्यूजवर लक्ष ठेवावे असे तुम्हाला वाटते त्या समाविष्ट करा: useEffect(() => { ... }, [dependency]). जेव्हा रेंडर्स दरम्यान dependency बदलते,