मैं रिएक्ट पर काम करता हूं।
TLDR:
लेकिन क्या आप राज्य को उसी क्रम में अपडेट करने के लिए रिएक्ट पर भरोसा कर सकते हैं जैसे कि सेटस्टेट के लिए कहा जाता है
हाँ।
हाँ।
आदेश अद्यतन की हमेशा सम्मान दिया जाता है। चाहे आप उन्हें "के बीच" एक मध्यवर्ती स्थिति देखते हैं या नहीं यह इस बात पर निर्भर करता है कि आप बैच में हैं या नहीं।
वर्तमान में (प्रतिक्रिया 16 और पूर्व), केवल प्रतिक्रिया इवेंट संचालकों के अंदर के अपडेट डिफ़ॉल्ट रूप से बैचबद्ध हैं । जरूरत पड़ने पर दुर्लभ मामलों के लिए ईवेंट हैंडलर के बाहर बैचिंग करने के लिए एक अस्थिर एपीआई है।
भविष्य के संस्करणों में (संभवत: 17 और बाद में प्रतिक्रिया), रिएक्ट डिफ़ॉल्ट रूप से सभी अपडेट को बैच देगा ताकि आपको इस बारे में सोचना न पड़े। हमेशा की तरह, हम रिएक्ट ब्लॉग पर और रिलीज़ नोट्स में इसके बारे में किसी भी बदलाव की घोषणा करेंगे ।
इसे समझने की कुंजी यह है कि कोई भी बात नहीं है कि एक रिएक्ट इवेंट हैंडलर के अंदरsetState()
आप कितने घटकों को कॉल करते हैं , वे इवेंट के अंत में केवल एक ही रेंडर प्रस्तुत करेंगे । यह बड़े अनुप्रयोगों में अच्छे प्रदर्शन के लिए महत्वपूर्ण है क्योंकि अगर Child
और Parent
प्रत्येक setState()
जब एक क्लिक इवेंट को संभालते हैं, तो आप Child
दो बार फिर से प्रस्तुत नहीं करना चाहते हैं ।
आपके दोनों उदाहरणों में, setState()
कॉल एक प्रतिक्रिया घटना हैंडलर के अंदर होती है। इसलिए वे हमेशा घटना के अंत में एक साथ बह जाते हैं (और आप मध्यवर्ती स्थिति नहीं देखते हैं)।
अद्यतन हमेशा उथले रूप से विलय के क्रम में होते हैं । तो अगर पहला अपडेट है {a: 10}
, दूसरा है {b: 20}
, और तीसरा है {a: 30}
, गाया हुआ राज्य होगा {a: 30, b: 20}
। एक ही राज्य कुंजी के लिए हाल ही में अद्यतन (जैसे a
मेरे उदाहरण में) हमेशा "जीतता है"।
this.state
वस्तु अद्यतन किया जाता है जब हम बैच के अंत में यूआई को फिर से प्रस्तुत करना। इसलिए यदि आपको पिछली स्थिति के आधार पर स्थिति को अपडेट करने की आवश्यकता है (जैसे कि एक काउंटर बढ़ाना), तो आपको उस कार्यात्मक setState(fn)
संस्करण का उपयोग करना चाहिए जो आपको पढ़ने के बजाय पिछले राज्य को देता है this.state
। यदि आप इसके लिए तर्क के बारे में उत्सुक हैं, तो मैंने इसे इस टिप्पणी में गहराई से समझाया ।
आपके उदाहरण में, हम "मध्यवर्ती स्थिति" नहीं देखेंगे क्योंकि हम एक रिएक्ट इवेंट हैंडलर के अंदर हैं जहाँ बैचिंग सक्षम है (क्योंकि रिएक्ट "जानता है" जब हम उस इवेंट से बाहर निकल रहे हैं)।
हालाँकि, रिएक्ट 16 और पुराने दोनों संस्करणों में, रिएक्ट इवेंट हैंडलर्स के बाहर डिफ़ॉल्ट रूप से कोई बैचिंग नहीं है । इसलिए यदि आपके उदाहरण में हमारे पास AJAX प्रतिक्रिया हैंडलर था handleClick
, तो प्रत्येक setState()
को तुरंत संसाधित किया जाएगा जैसा कि ऐसा होता है। इस मामले में, हां, आपको एक मध्यवर्ती स्थिति दिखाई देगी :
promise.then(() => {
// We're not in an event handler, so these are flushed separately.
this.setState({a: true}); // Re-renders with {a: true, b: false }
this.setState({b: true}); // Re-renders with {a: true, b: true }
this.props.setParentState(); // Re-renders the parent
});
हमें पता है कि यह असुविधाजनक है कि आप किसी घटना हैंडलर में हैं या नहीं, इस पर निर्भर करता है । यह भविष्य के रिएक्ट संस्करण में बदल जाएगा जो डिफ़ॉल्ट रूप से सभी अद्यतनों को बैच देगा (और तुल्यकालिक रूप से परिवर्तनों को फ्लश करने के लिए ऑप्ट-इन एपीआई प्रदान करता है)। जब तक हम डिफ़ॉल्ट व्यवहार को स्विच नहीं करते हैं (संभावित रूप से प्रतिक्रिया 17 में), तब एक एपीआई है जिसका उपयोग आप बैचिंग के लिए कर सकते हैं :
promise.then(() => {
// Forces batching
ReactDOM.unstable_batchedUpdates(() => {
this.setState({a: true}); // Doesn't re-render yet
this.setState({b: true}); // Doesn't re-render yet
this.props.setParentState(); // Doesn't re-render yet
});
// When we exit unstable_batchedUpdates, re-renders once
});
आंतरिक रूप से प्रतिक्रिया घटना संचालकों को लपेटा जा रहा unstable_batchedUpdates
है, इसीलिए वे डिफ़ॉल्ट रूप से बैचेन हैं। ध्यान दें कि अपडेट को unstable_batchedUpdates
दो बार लपेटने का कोई प्रभाव नहीं पड़ता है। जब हम सबसे बाहरी unstable_batchedUpdates
कॉल से बाहर निकलते हैं, तो अपडेट फ्लश हो जाते हैं ।
यह एपीआई इस अर्थ में "अस्थिर" है कि हम इसे तब निकाल देंगे जब बैचिंग पहले से ही डिफ़ॉल्ट रूप से सक्षम हो। हालांकि, हम इसे एक मामूली संस्करण में नहीं निकालेंगे, इसलिए आप रिएक्ट 17 तक सुरक्षित रूप से इस पर भरोसा कर सकते हैं यदि आपको रिएक्ट इवेंट हैंडलर्स के बाहर कुछ मामलों में बैचिंग को मजबूर करने की आवश्यकता है।
योग करने के लिए, यह एक भ्रमित करने वाला विषय है क्योंकि रिएक्ट केवल डिफ़ॉल्ट रूप से ईवेंट हैंडलर के अंदर बैचते हैं। यह भविष्य के संस्करणों में बदल जाएगा, और व्यवहार तब अधिक सीधा होगा। लेकिन समाधान कम बैच के लिए नहीं है , यह डिफ़ॉल्ट रूप से अधिक बैच करने के लिए है । यही हम करने जा रहे हैं।