कार्यात्मक प्रतिक्रिया घटक वर्ग-आधारित घटकों से कैसे भिन्न हैं?

कार्यात्मक प्रतिक्रिया घटक वर्ग-आधारित घटकों से कैसे भिन्न हैं? अभी कुछ समय के लिए, इस प्रश्न का पारंपरिक उत्तर है: "कक्षाओं का उपयोग आपको बड़ी संख्या में घटक क्षमताओं का उपयोग करने की अनुमति देता है, उदाहरण के लिए, राज्य।" अब, हुक के आगमन के साथ, यह उत्तर अब मामलों की सही स्थिति को नहीं दर्शाता है।

आपने सुना होगा कि इन प्रकार के घटकों में से एक का प्रदर्शन दूसरे की तुलना में बेहतर है। लेकिन कौन सा? अधिकांश बेंचमार्क जो इसका परीक्षण करते हैं उनमें खामियां हैं , इसलिए मैं बड़ी सावधानी के साथ उनके परिणामों के आधार पर निष्कर्ष निकालूंगा। प्रदर्शन मुख्य रूप से इस बात पर निर्भर करता है कि कोड में क्या हो रहा है, और इस पर नहीं कि कार्यात्मक क्षमताओं या वर्ग-आधारित घटकों को कुछ क्षमताओं को लागू करने के लिए चुना जाता है या नहीं। हमारे अध्ययन से पता चला है कि विभिन्न प्रकार के घटकों के बीच प्रदर्शन में अंतर नगण्य है। हालांकि, यह ध्यान दिया जाना चाहिए कि उनके साथ काम करने के लिए उपयोग की जाने वाली अनुकूलन रणनीतियाँ थोड़ी भिन्न होती हैं।



किसी भी मामले में, मैं नई तकनीकों का उपयोग करके मौजूदा घटकों को फिर से लिखने की अनुशंसा नहीं करता हूं अगर उसके लिए कोई अच्छे कारण नहीं हैं, और यदि आप उन लोगों के बीच बुरा नहीं मानते हैं, जिन्होंने बाकी सभी से पहले इन तकनीकों का उपयोग करना शुरू कर दिया है। हुक अभी भी एक नई तकनीक है (जैसा कि रिएक्ट लाइब्रेरी 2014 में था), और उनके आवेदन के लिए कुछ "सर्वोत्तम प्रथाओं" को अभी तक रिएक्ट मैनुअल में शामिल नहीं किया गया है।

हम आखिर कहाँ आ गए? क्या प्रतिक्रिया के कार्यात्मक घटकों और कक्षाओं के आधार पर घटकों के बीच कोई मौलिक अंतर हैं? बेशक, ऐसे मतभेद हैं। ये ऐसे घटकों के उपयोग के मानसिक मॉडल में अंतर हैं। इस लेख में मैं उनके सबसे गंभीर अंतर पर विचार करूंगा। यह 2015 से अस्तित्व में है, कार्यात्मक घटक दिखाई दिए, लेकिन अक्सर इसे अनदेखा किया जाता है। यह इस तथ्य में समाहित है कि कार्यात्मक घटक प्रदान किए गए मानों को पकड़ते हैं। आइए बात करते हैं कि वास्तव में इसका क्या मतलब है।

यह ध्यान दिया जाना चाहिए कि यह सामग्री विभिन्न प्रकार के घटकों का मूल्यांकन करने का प्रयास नहीं करती है। मैं सिर्फ रिएक्ट में दो प्रोग्रामिंग मॉडल के बीच अंतर का वर्णन करता हूं। यदि आप नवाचारों के प्रकाश में कार्यात्मक घटकों के उपयोग के बारे में अधिक जानना चाहते हैं, तो हुक पर प्रश्नों और उत्तरों की इस सूची को देखें।

कार्यों और कक्षाओं के आधार पर घटकों के कोड की विशेषताएं क्या हैं?


इस घटक पर विचार करें:

function ProfilePage(props) {  const showMessage = () => {    alert('Followed ' + props.user);  };  const handleClick = () => {    setTimeout(showMessage, 3000);  };  return (    <button onClick={handleClick}>Follow</button>  ); } 

यह एक बटन प्रदर्शित करता है, जो setTimeout फ़ंक्शन को दबाकर, नेटवर्क अनुरोध का अनुकरण करता है, और फिर ऑपरेशन की पुष्टि करने वाला एक संदेश बॉक्स प्रदर्शित करता है। उदाहरण के लिए, यदि ' props.user 'Dan' को props.user में संग्रहीत किया props.user , तो संदेश विंडो में, तीन सेकंड के बाद, 'Followed Dan' props.user 'Followed Dan' प्रदर्शित होगा।

ध्यान दें कि यदि एरो फ़ंक्शन या फ़ंक्शन घोषणाओं का उपयोग यहां किया जाता है, तो इससे कोई फर्क नहीं पड़ता। प्रपत्र function handleClick() का निर्माण ठीक उसी तरह से काम करेगा।

एक वर्ग के रूप में इस घटक को कैसे फिर से लिखना है? यदि आपने अभी-अभी कोड की जांच की है, तो उसे एक वर्ग के आधार पर एक घटक के कोड में परिवर्तित करके, आपको निम्नलिखित मिलेगा:

 class ProfilePage extends React.Component { showMessage = () => {   alert('Followed ' + this.props.user); }; handleClick = () => {   setTimeout(this.showMessage, 3000); }; render() {   return <button onClick={this.handleClick}>Follow</button>; } } 

यह आमतौर पर स्वीकार किया जाता है कि ऐसे दो कोड टुकड़े बराबर हैं। और डेवलपर्स अक्सर पूरी तरह से स्वतंत्र होते हैं, कोड रीफैक्टरिंग के दौरान, संभावित परिणामों के बारे में सोचने के बिना, एक को दूसरे में बदलना।


कोड के ये टुकड़े समतुल्य प्रतीत होते हैं

हालाँकि, इन कोड स्निपेट के बीच थोड़ा अंतर है। उन पर करीब से नज़र डालें। अंतर देखें? उदाहरण के लिए, मैंने उसे तुरंत नहीं देखा।

आगे हम इस अंतर पर विचार करेंगे, इसलिए, उन लोगों के लिए जो खुद को समझना चाहते हैं कि इस कोड का एक कार्यशील उदाहरण क्या है।

इससे पहले कि हम जारी रखें, मैं इस बात पर जोर देना चाहूंगा कि प्रश्न के अंतर का रिएक्ट हुक से कोई लेना-देना नहीं है। पिछले उदाहरणों में, वैसे, हुक का उपयोग भी नहीं किया जाता है। यह रिएक्ट में कार्यों और कक्षाओं के बीच अंतर के बारे में है। और यदि आप अपने रिएक्ट अनुप्रयोगों में कई कार्यात्मक घटकों का उपयोग करने की योजना बनाते हैं, तो आप इस अंतर को समझना चाह सकते हैं।

तथ्य की बात के रूप में, हम कार्यों और वर्गों के बीच अंतर को एक त्रुटि के उदाहरण से स्पष्ट करेंगे जो अक्सर प्रतिक्रिया अनुप्रयोगों में सामना होता है।

प्रतिक्रिया अनुप्रयोगों में आम त्रुटि है।


उदाहरण पृष्ठ खोलें जो एक सूची प्रदर्शित करता है जो आपको उपयोगकर्ता प्रोफ़ाइल का चयन करने की अनुमति देता है, और दो Follow बटन जो कि ProfilePageFunction और ProfilePageClass द्वारा प्रदर्शित होते हैं, कार्यात्मक, और वर्ग के आधार पर, जिनमें से कोड ऊपर दिखाया गया है।

निम्न क्रियाओं को करने के लिए, इनमें से प्रत्येक बटन के लिए प्रयास करें:

  1. बटन पर क्लिक करें।
  2. बटन पर क्लिक करने के बाद 3 सेकंड से पहले चयनित प्रोफ़ाइल को बदलें।
  3. संदेश बॉक्स में प्रदर्शित पाठ पढ़ें।

ऐसा करने के बाद, आप निम्नलिखित विशेषताएं देखेंगे:

  • जब आप चयनित Dan प्रोफाइल के साथ कार्यात्मक घटक द्वारा गठित बटन पर क्लिक करते हैं और फिर Sophie प्रोफाइल पर स्विच करते हैं, तो संदेश बॉक्स में 'Followed Dan' प्रदर्शित होगा।
  • यदि आप एक वर्ग के आधार पर एक घटक द्वारा गठित बटन के साथ करते हैं, तो 'Followed Sophie' प्रदर्शित किया जाएगा।


कक्षा-आधारित घटक सुविधाएँ

इस उदाहरण में, कार्यात्मक घटक का व्यवहार सही है। यदि मैंने किसी की प्रोफ़ाइल को सब्सक्राइब किया है, और फिर किसी अन्य प्रोफ़ाइल पर स्विच किया है, तो मेरे घटक को संदेह नहीं होना चाहिए कि मैंने किसकी प्रोफ़ाइल की सदस्यता ली है। जाहिर है, कक्षाओं के उपयोग के आधार पर प्रश्न में तंत्र के कार्यान्वयन में एक त्रुटि होती है (वैसे, आपको निश्चित रूप से सोफिया का ग्राहक बनना चाहिए)।

कक्षा-आधारित घटक की खराबी के कारण


क्लास-आधारित घटक इस तरह से व्यवहार क्यों करता है? इसे समझने के लिए, आइए एक नज़र डालते हैं हमारी कक्षा में प्रदर्शन विधि:

 class ProfilePage extends React.Component { showMessage = () => {   alert('Followed ' + this.props.user); }; 

यह विधि इस से डेटा पढ़ता है। रिएक्ट में गुण अपरिवर्तनीय हैं, इसलिए वे बदलते नहीं हैं। हालांकि, this , हमेशा की तरह, एक उत्परिवर्तनीय इकाई है।

वास्तव में, this एक कक्षा में रखने का उद्देश्य this बदलने की क्षमता में निहित है। रिएक्ट लाइब्रेरी स्वयं समय-समय पर this परिवर्तन को करती है, जो render विधि और घटक जीवन चक्र विधियों के नवीनतम संस्करणों के साथ काम करने की अनुमति देता है।

परिणामस्वरूप, यदि हमारा घटक अनुरोध के निष्पादन के दौरान पुन: प्रतिपादन करता है, तो यह। परिवर्तन बदल जाएगा। उसके बाद, showMessage विधि "बहुत नई" props इकाई से user मूल्य को showMessage

यह आपको उपयोगकर्ता इंटरफेस के बारे में एक दिलचस्प अवलोकन करने की अनुमति देता है। यदि हम कहते हैं कि उपयोगकर्ता इंटरफ़ेस, वैचारिक रूप से, एप्लिकेशन की वर्तमान स्थिति का एक फ़ंक्शन है, तो ईवेंट हैंडलर रेंडरिंग परिणामों का हिस्सा है - ठीक दृश्य रेंडरिंग परिणामों की तरह। हमारे इवेंट हैंडलर विशिष्ट गुणों और राज्य के साथ एक विशिष्ट रेंडरिंग ऑपरेशन के लिए "संबंधित" हैं।

हालाँकि, टाइमआउट शेड्यूल करना जिसका कॉलबैक है। this.props इस कनेक्शन का उल्लंघन करता है। ShowMessage showMessage किसी विशेष रेंडरिंग ऑपरेशन के लिए "बंधा" नहीं है, नतीजतन, यह सही गुण "खो देता है"। इससे डेटा पढ़ना इस कनेक्शन को तोड़ देता है।

समस्या को हल करने के लिए वर्ग-आधारित घटकों के माध्यम से कैसे?


कल्पना कीजिए कि रिएक्ट में कोई कार्यात्मक घटक नहीं हैं। फिर इस समस्या को कैसे हल करें?

हमें सही गुणों और शो मेसेज showMessage साथ render विधि के बीच संबंध को "बहाल" करने के लिए कुछ तंत्र की आवश्यकता है, जो गुणों से डेटा पढ़ता है। यह तंत्र कहीं पर स्थित होना चाहिए जहां सही डेटा के साथ props का सार खो जाता है।

इसे करने का एक तरीका यह है कि इस घटना हैंडलर में पहले से पढ़ लें। और फिर setTimeout में उपयोग किए गए कॉलबैक फ़ंक्शन को स्पष्ट रूप से पढ़ें।

 class ProfilePage extends React.Component { showMessage = (user) => {   alert('Followed ' + user); }; handleClick = () => {   const {user} = this.props;   setTimeout(() => this.showMessage(user), 3000); }; render() {   return <button onClick={this.handleClick}>Follow</button>; } } 

यह दृष्टिकोण काम कर रहा है । लेकिन समय के साथ यहां उपयोग किए जाने वाले अतिरिक्त निर्माण, कोड की मात्रा में वृद्धि और इस तथ्य की ओर बढ़ेंगे कि इसमें त्रुटियों की संभावना बढ़ जाएगी। यदि हमें एक से अधिक संपत्ति की आवश्यकता हो तो क्या होगा? अगर हमें राज्य के साथ काम करने की आवश्यकता है, तो क्या होगा? यदि this.state.something विधि किसी अन्य विधि को showMessage करती है और यह विधि इसे पढ़ती है। this.state.something या this.state.something , तो हम फिर से उसी समस्या का सामना करेंगे। और इसे हल करने के लिए, हमें यह पास करना होगा। यह this.state और showMessage से बुलाए गए सभी तरीकों पर बहस करें।

यदि ऐसा करना सही है, तो यह उन सभी आवश्यकताओं को नष्ट कर देगा जो कक्षाओं के आधार पर घटकों का उपयोग करती हैं। तथ्य यह है कि आपको इस तरह से तरीकों के साथ काम करने की आवश्यकता है, यह याद रखना मुश्किल है, स्वचालित करना मुश्किल है, परिणामस्वरूप, डेवलपर्स अक्सर समान तरीकों का उपयोग करने के बजाय, सहमत होते हैं कि उनकी परियोजनाओं में त्रुटियां हैं।

इसी तरह, handleClick में alert कोड एम्बेड करना अधिक वैश्विक समस्या का समाधान नहीं करता है। हमें कोड की संरचना करने की आवश्यकता है ताकि इसे कई विधियों में विभाजित किया जा सके, लेकिन यह भी कि हम उन संपत्तियों और अवस्थाओं को पढ़ सकें जो किसी विशेष कॉल से जुड़े रेंडरिंग ऑपरेशन के अनुरूप हैं। वैसे, यह समस्या, विशेष रूप से रिएक्ट के लिए भी लागू नहीं होती है। आप इसे उपयोगकर्ता इंटरफ़ेस विकसित करने के लिए किसी भी लाइब्रेरी में खेल सकते हैं, जो this तरह के परस्पर वस्तुओं में डेटा डालता है।

हो सकता है कि इस समस्या को हल करने के लिए, आप विधायक में इसके तरीकों को बांध सकते हैं?

 class ProfilePage extends React.Component { constructor(props) {   super(props);   this.showMessage = this.showMessage.bind(this);   this.handleClick = this.handleClick.bind(this); } showMessage() {   alert('Followed ' + this.props.user); } handleClick() {   setTimeout(this.showMessage, 3000); } render() {   return <button onClick={this.handleClick}>Follow</button>; } } 

लेकिन इससे हमारी समस्या हल नहीं होती है। याद रखें कि यह है कि हम this.props से डेटा पढ़ रहे हैं। बहुत देर हो चुकी है, और उपयोग किए गए वाक्यविन्यास में नहीं! हालाँकि, यह समस्या हल हो जाएगी यदि हम जावास्क्रिप्ट क्लोजर पर भरोसा करते हैं।

डेवलपर्स अक्सर क्लोजर से बचने की कोशिश करते हैं, क्योंकि समय के साथ-साथ उन मूल्यों के बारे में सोचना आसान नहीं है, जो म्यूट नहीं कर सकते। लेकिन रिएक्ट में गुण अपरिवर्तनीय हैं! (या, कम से कम, यह अत्यधिक अनुशंसित है)। यह आपको कुछ के रूप में बंद होने की धारणा को रोकने की अनुमति देता है जिसके कारण प्रोग्रामर, जैसा कि वे कहते हैं, "पैर में खुद को गोली मार सकते हैं"।

इसका मतलब यह है कि यदि आप किसी विशेष रेंडरिंग ऑपरेशन के गुणों या स्थिति को "लॉक" करते हैं, तो आप हमेशा उन्हें बदल सकते हैं।

 class ProfilePage extends React.Component { render() {   //  !   const props = this.props;   //    ,      render.   //   -   .   const showMessage = () => {     alert('Followed ' + props.user);   };   const handleClick = () => {     setTimeout(showMessage, 3000);   };   return <button onClick={handleClick}>Follow</button>; } } 

जैसा कि आप देख सकते हैं, यहां हमने render विधि के लिए कॉल के दौरान गुणों को "कैप्चर" किया है।


कॉल रेंडर द्वारा कैप्चर किए गए गुण

इस दृष्टिकोण के साथ, किसी भी कोड जो कि render विधि ( showMessage सहित) में है, इस पद्धति के लिए किसी विशेष कॉल के दौरान कैप्चर किए गए गुणों को देखने की गारंटी है। परिणामस्वरूप, प्रतिक्रिया अब हमें वह करने से रोक नहीं पाएगी जिसकी हमें आवश्यकता है।

render विधि में, आप जितने चाहें उतने सहायक कार्यों का वर्णन कर सकते हैं और उनमें से सभी "कैप्चर किए गए" गुणों और स्थिति का उपयोग करने में सक्षम होंगे। इस तरह बंद होने से हमारी समस्या हल हो गई।

क्लोजर का उपयोग करके समस्या के समाधान का विश्लेषण


हम अभी-अभी पहुंचे हमें समस्या को हल करने की अनुमति देता है , लेकिन ऐसा कोड अजीब लगता है। render मेथड के अंदर फंक्शंस घोषित होने पर क्लास की आवश्यकता क्यों होती है, न कि क्लास मेथड के रूप में?

हम, वास्तव में, इसे घेरने वाले वर्ग के रूप में "शेल" से छुटकारा पाकर इस कोड को सरल बना सकते हैं:

 function ProfilePage(props) { const showMessage = () => {   alert('Followed ' + props.user); }; const handleClick = () => {   setTimeout(showMessage, 3000); }; return (   <button onClick={handleClick}>Follow</button> ); } 

यहां, पिछले उदाहरण की तरह, गुणों को फ़ंक्शन में कैप्चर किया गया है, क्योंकि रिएक्ट उन्हें एक तर्क के रूप में पास करता है। इसके विपरीत, रिएक्ट कभी भी props ऑब्जेक्ट को म्यूट नहीं करता है।

यह थोड़ा और स्पष्ट हो जाता है यदि props फ़ंक्शन घोषणा में नष्ट हो props :

 function ProfilePage({ user }) { const showMessage = () => {   alert('Followed ' + user); }; const handleClick = () => {   setTimeout(showMessage, 3000); }; return (   <button onClick={handleClick}>Follow</button> ); } 

जब मूल घटक अन्य गुणों के साथ ProfilePage को ProfilePage , तो React ProfilePage फ़ंक्शन को कॉल करेगा। लेकिन ईवेंट हैंडलर जिसे पहले से ही इस फ़ंक्शन के लिए "कॉल" के लिए "संबंधित" कहा जाता है, यह कॉल अपने स्वयं के user मूल्य और अपने स्वयं के शो मेसेज showMessage का उपयोग करता है, जो इस मूल्य को पढ़ता है। यह सब अछूता रह जाता है।

यही कारण है कि हमारे उदाहरण के मूल संस्करण में, जब एक कार्यात्मक घटक के साथ काम करते हैं, तो संदेश प्रदर्शित होने से पहले संबंधित बटन पर क्लिक करने के बाद किसी अन्य प्रोफ़ाइल का चयन करने से कुछ भी नहीं बदलता है। यदि बटन पर क्लिक करने से पहले एक Sophie प्रोफ़ाइल का चयन किया गया था, तो संदेश विंडो में 'Followed Sophie' प्रदर्शित किया जाएगा, चाहे कुछ भी हो।


एक कार्यात्मक घटक का उपयोग करना

यह व्यवहार सही है (आप चाहें तो सुनील के लिए साइन अप भी कर सकते हैं)।

अब हमने यह पता लगा लिया है कि रिएक्ट में फ़ंक्शंस और क्लासेस में क्या बड़ा अंतर है। जैसा कि पहले ही उल्लेख किया गया है, हम इस तथ्य के बारे में बात कर रहे हैं कि कार्यात्मक घटक मूल्यों को पकड़ते हैं। अब बात करते हैं हुक की।

hooky


हुक का उपयोग करते समय, "कैप्चरिंग वैल्यू" का सिद्धांत राज्य तक फैला हुआ है। निम्नलिखित उदाहरण पर विचार करें:

 function MessageThread() { const [message, setMessage] = useState(''); const showMessage = () => {   alert('You said: ' + message); }; const handleSendClick = () => {   setTimeout(showMessage, 3000); }; const handleMessageChange = (e) => {   setMessage(e.target.value); }; return (   <>     <input value={message} onChange={handleMessageChange} />     <button onClick={handleSendClick}>Send</button>   </> ); } 

यहाँ आप उसके साथ प्रयोग कर सकते हैं

हालाँकि यह एक संदेश अनुप्रयोग इंटरफ़ेस का एक अनुकरणीय उदाहरण नहीं है, यह परियोजना एक ही विचार को दर्शाती है: यदि किसी उपयोगकर्ता ने एक संदेश भेजा है, तो घटक को भ्रमित नहीं होना चाहिए कि कौन सा संदेश भेजा गया था। इस कार्यात्मक घटक का message निरंतर उस स्थिति को कैप्चर करता है जो उस घटक से "संबंधित" होती है जो ब्राउज़र को उस बटन के लिए क्लिक हैंडलर प्रदान करता है जिसे वह कॉल करता है। परिणामस्वरूप, message बटन Send बटन पर क्लिक करते समय इनपुट फ़ील्ड में क्या था।

कार्यात्मक घटकों द्वारा गुणों और राज्यों को कैप्चर करने की समस्या


हम जानते हैं कि प्रतिक्रियात्मक रूप से कार्यात्मक घटक, डिफ़ॉल्ट रूप से, गुणों और स्थिति को कैप्चर करते हैं। लेकिन क्या होगा यदि हमें संपत्तियों या राज्यों के नवीनतम डेटा को पढ़ने की आवश्यकता है जो किसी विशेष फ़ंक्शन कॉल से संबंधित नहीं हैं? क्या होगा यदि हम उन्हें " भविष्य से पढ़ना " चाहते हैं?

क्लास-आधारित घटकों में, यह केवल this.state या this.state संदर्भ में किया जा सकता है, क्योंकि this एक उत्परिवर्ती इकाई है। उसका बदलाव रिएक्ट में लगा हुआ है। कार्यात्मक घटक उन उत्परिवर्तनीय मूल्यों के साथ भी काम कर सकते हैं जो सभी घटकों द्वारा साझा किए जाते हैं। इन मूल्यों को ref कहा जाता है:

 function MyComponent() { const ref = useRef(null); //     `ref.current`. // ... } 

हालांकि, प्रोग्रामर को ऐसे मूल्यों का स्वतंत्र रूप से प्रबंधन करने की आवश्यकता है।

ref का सार उसी तरह की भूमिका निभाता है जैसे किसी वर्ग के उदाहरण के क्षेत्र। यह एक परिवर्तनशील अनिवार्य दुनिया में एक "आपातकालीन निकास" है। आप डोम रिफ की अवधारणा से परिचित हो सकते हैं, लेकिन यह विचार बहुत अधिक सामान्य है। इसकी तुलना एक बॉक्स से की जा सकती है जिसमें कोई प्रोग्रामर कुछ डाल सकता है।

बाहरी रूप से भी, इस this.something निर्माण का एक दर्पण जैसा दिखता something.current । वे उसी अवधारणा के परिचायक हैं।

डिफ़ॉल्ट रूप से, प्रतिक्रिया सबसे हाल ही में संपत्ति या राज्य मूल्यों के लिए कार्यात्मक घटकों में ref संस्थाओं का निर्माण नहीं करती है। कई मामलों में, आपको उनकी आवश्यकता नहीं होगी, और उनकी स्वचालित रचना समय की बर्बादी होगी। हालाँकि, यदि आवश्यक हो, तो उनके साथ काम किया जा सकता है:

 function MessageThread() { const [message, setMessage] = useState(''); const latestMessage = useRef(''); const showMessage = () => {   alert('You said: ' + latestMessage.current); }; const handleSendClick = () => {   setTimeout(showMessage, 3000); }; const handleMessageChange = (e) => {   setMessage(e.target.value);   latestMessage.current = e.target.value; }; 

यदि हम message को showMessage में पढ़ते हैं, तो हम उस संदेश को देखेंगे जो Send बटन पर क्लिक करते समय फ़ील्ड में था। लेकिन अगर आप latestMessage.current पढ़ते हैं, तो आप नवीनतम मान प्राप्त कर सकते हैं - भले ही हम Send बटन पर क्लिक करने के बाद क्षेत्र में पाठ दर्ज करना जारी रखें।

स्वतंत्र रूप से अंतर का मूल्यांकन करने के लिए आप इस और इस उदाहरण की तुलना कर सकते हैं। ref का मान रेंडरिंग की एकरूपता से "बचने" का एक तरीका है, कुछ मामलों में यह बहुत उपयोगी हो सकता है।

सामान्य तौर पर, आपको रेंडरिंग प्रक्रिया के दौरान ref वैल्यू को पढ़ने या लिखने से बचना चाहिए क्योंकि ये वैल्यू म्यूट हैं। हम प्रतिपादन को पूर्वानुमेय बनाने का प्रयास करते हैं। हालांकि, अगर हमें संपत्तियों या राज्य में संग्रहित किसी चीज़ का सबसे हालिया मूल्य प्राप्त करने की आवश्यकता है, तो मैन्युअल रूप से ref मूल्य को अपडेट करना एक थकाऊ काम हो सकता है। यह प्रभाव का उपयोग कर स्वचालित किया जा सकता है:

 function MessageThread() { const [message, setMessage] = useState(''); //    . const latestMessage = useRef(''); useEffect(() => {   latestMessage.current = message; }); const showMessage = () => {   alert('You said: ' + latestMessage.current); }; 

यहाँ एक उदाहरण है जो इस कोड का उपयोग करता है

हम प्रभाव के अंदर एक मूल्य प्रदान कर रहे हैं, परिणामस्वरूप, DOM के अपडेट होने के बाद ही ref का मूल्य बदल जाएगा। यह सुनिश्चित करता है कि हमारा उत्परिवर्तन टाइम स्लाइसिंग और सस्पेंस जैसी सुविधाओं को बाधित नहीं करता है, जो रेंडरिंग संचालन की निरंतरता पर निर्भर करता है।

इस तरह ref मूल्य का उपयोग करना अक्सर आवश्यक नहीं होता है। कैप्चरिंग प्रॉपर्टीज या स्टेट्स आमतौर पर स्टैंडर्ड सिस्टम बिहेवियर का ज्यादा बेहतर पैटर्न प्रतीत होते हैं। हालाँकि, यह सुविधाजनक एपीआई के साथ काम करते समय सुविधाजनक हो सकता है, जैसे अंतराल या सदस्यता का उपयोग करने वाले। याद रखें कि आप इस तरह से काम कर सकते हैं - गुणों के साथ, राज्य में संग्रहीत चर के साथ, पूरे props ऑब्जेक्ट के साथ props या यहां तक ​​कि एक फ़ंक्शन के साथ।

यह पैटर्न, इसके अलावा, अनुकूलन उद्देश्यों के लिए उपयोगी हो सकता है। उदाहरण के लिए, जब कुछ उपयोग जैसे कि useCallback बहुत बार बदलता है। सच है, एक रेड्यूसर का उपयोग करने के लिए पसंदीदा समाधान अक्सर होता है।

परिणाम


इस लेख में, हमने क्लास-आधारित घटकों का उपयोग करने के लिए एक गलत पैटर्न को देखा और इस समस्या को बंद करने के साथ कैसे हल किया जाए, इस बारे में बात की। हालाँकि, आप देख सकते हैं कि जब आप निर्भरता की एक सरणी निर्दिष्ट करके हुक का अनुकूलन करने का प्रयास करते हैं, तो आप अप्रचलित बंदियों से संबंधित त्रुटियों का सामना कर सकते हैं। क्या इसका मतलब यह है कि दोष स्वयं एक समस्या है। मुझे ऐसा नहीं लगता।

जैसा कि ऊपर दिखाया गया है, क्लोजर, वास्तव में, छोटी समस्याओं को ठीक करने में हमारी मदद करते हैं जो नोटिस करना मुश्किल है। इसी तरह, वे समानांतर में सही ढंग से काम करने वाले कोड को लिखना आसान बनाते हैं । यह इस तथ्य के कारण संभव है कि घटक के अंदर सही गुण और राज्य जिसके साथ यह घटक प्रदान किया गया था, "बंद" हैं।

अब तक मैंने देखा कि सभी मामलों में, "अप्रचलित बंद होने" की समस्या गलत धारणा के कारण हुई है कि "कार्य नहीं बदलते हैं", या यह कि "गुण हमेशा समान रहते हैं"। मुझे उम्मीद है कि इस सामग्री को पढ़ने के बाद, आप आश्वस्त हैं कि ऐसा नहीं है।

कार्य उनके गुणों और स्थिति को "कैप्चर" करते हैं - और इसलिए यह समझना कि कौन से कार्य प्रश्न में हैं, यह भी महत्वपूर्ण है। यह एक गलती नहीं है, यह कार्यात्मक घटकों की एक विशेषता है। उदाहरण के लिए, useEffect या useCalback लिए "निर्भरता की सरणी" से कार्यों को बाहर नहीं किया जाना चाहिए। (समस्या को हल करने के लिए एक उपयुक्त उपकरण आमतौर पर या तो उपयोग किया जाता useReducer या useRef । हम इसके बारे में ऊपर बात करते हैं, और जल्द ही हम ऐसी सामग्री तैयार करेंगे जो इस या उस दृष्टिकोण की पसंद के लिए समर्पित होगी)।

यदि हमारे अनुप्रयोगों में अधिकांश कोड कार्यात्मक घटकों पर आधारित होगा, तो इसका मतलब है कि हमें कोड अनुकूलन के बारे में अधिक जानने की आवश्यकता है, और समय के साथ क्या मूल्य बदल सकते हैं

: « , , , , , ».

. , React , . , « », . , React .

, , .


React —

Source: https://habr.com/ru/post/hi444348/


All Articles