जैसे-जैसे वेब एप्लिकेशन बढ़ता है, यह सभी डेटा फ्लो पर नज़र रखना एक चुनौती बन जाता है। किस कोड को डेटा मिलता है, कौन सा पेज इसका उपभोग करता है, कहां और कब इसे अपडेट करने की आवश्यकता होती है ... गंदे कोड को समाप्त करना आसान है जिसे बनाए रखना मुश्किल है। यह विशेष रूप से सच है जब आपको अपने ऐप के विभिन्न पृष्ठों के बीच डेटा साझा करने की आवश्यकता होती है, उदाहरण के लिए उपयोगकर्ता डेटा। *स्टेट प्रबंधन* की अवधारणा हमेशा सभी प्रकार के कार्यक्रमों में मौजूद रही है, लेकिन जैसा कि वेब ऐप जटिलता में बढ़ रहे हैं, यह अब विकास के दौरान सोचने का एक महत्वपूर्ण बिंदु है।
इस अंतिम भाग में, हम उस ऐप पर नज़र डालेंगे जिसे हमने बनाया है कि स्टेट कैसे प्रबंधित किया जाता है, किसी भी बिंदु पर ब्राउज़र रीफ्रेश के लिए समर्थन और उपयोगकर्ता सत्रों में डेटा को बनाए रखने की अनुमति देता है।
आपको इस पाठ के लिए वेब ऐप का [डेटा प्राप्त करने](../../3-data/translations/README.hi.md) वाला भाग पूरा करना होगा। आपको स्थानीय रूप से [Node.js](https://nodejs.org) और [सर्वर एपीआई चलाने](../../api/translations/README.hi.md) को स्थापित करने की आवश्यकता है ताकि आप खाता डेटा प्रबंधित कर सकें।
[पिछले पाठ](../../3-data/translations/README.hi.md) में, हमने अपने ऐप में वैश्विक `account` चर के साथ स्टेट की एक बुनियादी अवधारणा पेश की, जिसमें वर्तमान में लॉग इन उपयोगकर्ता के लिए बैंक डेटा शामिल है। हालांकि, हमारे वर्तमान कार्यान्वयन में कुछ खामियां हैं। जब आप डैशबोर्ड पर हों तो पृष्ठ को ताज़ा करने का प्रयास करें। क्या होता है?
- स्टेट कायम नहीं है, क्योंकि ब्राउज़र रीफ़्रेश आपको लॉगिन पृष्ठ पर वापस ले जाता है।
- स्टेट को संशोधित करने वाले कई कार्य हैं। जैसे-जैसे ऐप बढ़ता है, यह परिवर्तनों को ट्रैक करना मुश्किल बना सकता है और किसी एक को अपडेट करना भूल जाना आसान है।
- स्टेट को साफ नहीं किया जाता है, इसलिए जब आप * लॉगआउट * पर क्लिक करते हैं, तो खाता डेटा अभी भी वहीं है जबकि आप लॉगिन पेज पर हैं।
हम एक-एक करके इन मुद्दों से निपटने के लिए अपने कोड को अपडेट कर सकते हैं, लेकिन यह अधिक कोड दोहराव पैदा करेगा और ऐप को अधिक जटिल और बनाए रखना मुश्किल होगा। या हम कुछ मिनटों के लिए रुक सकते हैं और अपनी रणनीति पर फिर से विचार कर सकते हैं।
एक बार जब आप इनका ध्यान रख लेते हैं, तो हो सकता है कि कोई अन्य समस्या या तो पहले से ही ठीक हो जाए या जिसे ठीक करना आसान हो जाए। इन समस्याओं को हल करने के लिए कई संभावित दृष्टिकोण हैं, लेकिन हम एक सामान्य समाधान के साथ जाएंगे जिसमें डेटा को **केंद्रीकृत करना और इसे बदलने के तरीके** शामिल हैं। डेटा प्रवाह इस तरह होगा:
> हम यहां उस हिस्से को कवर नहीं करेंगे जहां डेटा स्वचालित रूप से दृश्य अद्यतन को ट्रिगर करता है, क्योंकि यह [रीऐक्टिव प्रोग्रामिंग](https://en.wikipedia.org/wiki/Reactive_programming) की अधिक उन्नत अवधारणाओं से बंधा है। यदि आप एक गहरी गोता लगाने के लिए एक अच्छा अनुवर्ती विषय है।
✅ स्टेट प्रबंधन के विभिन्न दृष्टिकोणों के साथ वहाँ बहुत सारे पुस्तकालय हैं, [Redux](https://redux.js.org) एक लोकप्रिय विकल्प है। उपयोग की जाने वाली अवधारणाओं और पैटर्नों पर एक नज़र डालें क्योंकि यह अक्सर सीखने का एक अच्छा तरीका है कि आप बड़े वेब ऐप में किन संभावित मुद्दों का सामना कर रहे हैं और इसे कैसे हल किया जा सकता है।
एक स्टेट वस्तु में हमारे सभी एप्लिकेशन डेटा को *केंद्रीकृत* करने का विचार है। हमारे पास स्टेट में अभी के लिए `account` है, इसलिए यह बहुत अधिक नहीं बदलता है, लेकिन यह प्रस्तावों के लिए एक रास्ता बनाता है।
अब जब हमने अपने डेटा को स्टोर करने के लिए `state` ऑब्जेक्ट को रखा है, तो अगला चरण अपडेट को केंद्रीकृत करना है। लक्ष्य किसी भी परिवर्तन का ट्रैक रखना आसान है और जब वे होते हैं।
`state` वस्तु में किए गए परिवर्तनों से बचने के लिए, यह [*अपरिवर्तनीय*](https://en.wikipedia.org/wiki/Immutable_object) पर विचार करने के लिए एक अच्छा अभ्यास है, जिसका अर्थ है कि इसे बिल्कुल भी संशोधित नहीं किया जा सकता है। इसका अर्थ यह भी है कि यदि आप इसमें कुछ भी बदलना चाहते हैं तो आपको एक नया स्टेट ऑब्जेक्ट बनाना होगा। ऐसा करने से, आप संभावित रूप से अवांछित [साइड इफेक्ट्स](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) के बारे में एक सुरक्षा का निर्माण करते हैं, और अपने ऐप में नई सुविधाओं के लिए संभावनाएं खोलते हैं जैसे कि undo/redo को लागू करना, जबकि डिबग करना भी आसान है। उदाहरण के लिए, आप स्टेट में किए गए प्रत्येक परिवर्तन को लॉग कर सकते हैं और बग के स्रोत को समझने के लिए परिवर्तनों का इतिहास रख सकते हैं।
जावास्क्रिप्ट में, आप एक अपरिवर्तनीय संस्करण एक ऑब्जेक्ट बनाने के लिए [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) का उपयोग कर सकते हैं । यदि आप एक अपरिवर्तनीय वस्तु में परिवर्तन करने की कोशिश करते हैं, तो एक अपवाद उठाया जाएगा।
✅ क्या आप एक *उथले* और एक *गहरी* अपरिवर्तनीय वस्तु के बीच का अंतर जानते हैं? आप इसके बारे में [यहां](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) पढ़ सकते हैं.
इस फ़ंक्शन में, हम [*spread (`...`) operator*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) का उपयोग करके पिछले स्टेट से एक नया स्टेट ऑब्जेक्ट और कॉपी डेटा बना रहे हैं। फिर हम नए डेटा के साथ स्टेट ऑब्जेक्ट की एक विशेष प्रॉपर्टी को ओवरराइड करते हैं [ब्रैकेट नोटेशन] `[property]` असाइनमेंट के लिए। अंत में, हम `Object.freeze()` का उपयोग करके संशोधनों को रोकने के लिए ऑब्जेक्ट को लॉक करते हैं। हमारे पास अब केवल स्टेट में संग्रहीत `अकाउंट` प्रॉपर्टी है, लेकिन इस दृष्टिकोण के साथ आप स्टेट में जितनी आवश्यकता हो उतने गुण जोड़ सकते हैं।
युक्ति: आप `updateState()` के तल पर `console.log(state)` जोड़कर और अपने ब्राउज़र के डेवलपमेंट टूल में कंसोल खोलकर सभी स्टेट परिवर्तनों पर एक नज़र डाल सकते हैं।
अधिकांश वेब ऐप्स को डेटा को सही ढंग से काम करने में सक्षम बनाने के लिए लगातार बने रहने की आवश्यकता होती है। सभी महत्वपूर्ण डेटा को आमतौर पर डेटाबेस पर संग्रहीत किया जाता है और सर्वर एपीआई के माध्यम से एक्सेस किया जाता है, जैसे हमारे मामले में उपयोगकर्ता खाता डेटा। लेकिन कभी-कभी, एक बेहतर उपयोगकर्ता अनुभव के लिए या लोडिंग प्रदर्शन में सुधार करने के लिए आपके ब्राउज़र में चल रहे क्लाइंट ऐप पर कुछ डेटा को जारी रखना भी दिलचस्प है।
- *क्या डेटा संवेदनशील है?* आपको क्लाइंट पर किसी भी संवेदनशील डेटा, जैसे उपयोगकर्ता पासवर्ड को संग्रहीत करने से बचना चाहिए।
- *आपको यह डेटा कब तक रखने की आवश्यकता है?* क्या आप इस डेटा को केवल वर्तमान सत्र के लिए एक्सेस करने की योजना बना रहे हैं या क्या आप चाहते हैं कि यह हमेशा के लिए स्टोर हो जाए?
वेब ऐप के अंदर जानकारी संग्रहीत करने के कई तरीके हैं, जो इस बात पर निर्भर करता है कि आप क्या हासिल करना चाहते हैं। उदाहरण के लिए, आप खोज क्वेरी को संग्रहीत करने के लिए URL का उपयोग कर सकते हैं, और इसे उपयोगकर्ताओं के बीच साझा करने योग्य बना सकते हैं। यदि आप डेटा को सर्वर के साथ साझा करने की आवश्यकता है, जैसे कि [authentication](https://en.wikipedia.org/wiki/Authentication) की जानकारी।
- [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage): एक [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) विभिन्न सत्रों में वर्तमान वेब साइट के लिए विशिष्ट डेटा को बनाए रखने की अनुमति देते हैं। इसमें सहेजा गया डेटा कभी समाप्त नहीं होता है।
- [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage): यह एक `sessionStorage` की तरह ही काम करता है, सिवाय इसके कि इसमें संग्रहीत डेटा सत्र समाप्त होने पर (जब ब्राउज़र बंद हो जाता है) साफ हो जाता है।
यदि आप जटिल वस्तुओं को संग्रहीत करना चाहते हैं, तो आपको इसे [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) प्रारूप [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) का उपयोग करके क्रमबद्ध करना होगा।
✅ यदि आप एक वेब ऐप बनाना चाहते हैं जो सर्वर के साथ काम नहीं करता है, तो [`IndexedDB` API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) का उपयोग करके क्लाइंट पर डेटाबेस बनाना भी संभव है। यह एक उन्नत उपयोग मामलों के लिए आरक्षित है या यदि आपको महत्वपूर्ण मात्रा में डेटा संग्रहीत करने की आवश्यकता है, क्योंकि यह उपयोग करने के लिए अधिक जटिल है।
हम चाहते हैं कि हमारे उपयोगकर्ता तब तक लॉग इन रहें जब तक कि वे स्पष्ट रूप से *लॉगआउट* बटन पर क्लिक न करें, इसलिए हम खाता डेटा संग्रहीत करने के लिए `localStorage` का उपयोग करेंगे। सबसे पहले, एक कुंजी परिभाषित करते हैं जिसका उपयोग हम अपने डेटा को संग्रहीत करने के लिए करेंगे।.
इसके साथ, उपयोगकर्ता खाते के डेटा को बनाए रखा जाएगा और हमेशा अप-टू-डेट रहेगा क्योंकि हमने अपने सभी स्टेट अपडेट पहले केंद्रीकृत किए थे। यह वह जगह है जहाँ हम अपने सभी पिछले रिफ्लेक्टरों से लाभान्वित होने लगते हैं 🙂.
डेटा सहेजे जाने के साथ, हमें ऐप को लोड करने पर इसे पुनर्स्थापित करने का भी ध्यान रखना होगा। चूंकि हम अधिक आरंभीकरण कोड शुरू करेंगे, इसलिए यह एक नया `init` फ़ंक्शन बनाने के लिए एक अच्छा विचार हो सकता है, जिसमें `app.js` के नीचे हमारा पिछला कोड भी शामिल है।:
यहां हम सहेजे गए डेटा को पुनर्प्राप्त करते हैं, और यदि कोई है तो हम तदनुसार स्टेट को अपडेट करते हैं। रूट अपडेट करने से *पहले* इसे करना महत्वपूर्ण है, क्योंकि पेज अपडेट के दौरान स्टेट पर कोड निर्भर हो सकता है।
हम अपने एप्लिकेशन डिफॉल्ट पेज को भी * डैशबोर्ड * पेज बना सकते हैं, क्योंकि हम अब खाता डेटा को जारी रख रहे हैं। यदि कोई डेटा नहीं मिला है, तो डैशबोर्ड * लॉगिन * पेज वैसे भी पुनर्निर्देशित करने का ख्याल रखता है। `updateRoute()` में, फ़ॉलबैक `return navigate('/login');` को `return navigate('/dashboard');` से बदलें।
अब ऐप में लॉगइन करें और पेज को रिफ्रेश करने की कोशिश करें। आपको डैशबोर्ड पर रहना चाहिए। उस अपडेट के साथ हमने अपने सभी शुरुआती मुद्दों का ध्यान रखा है ...
स्टेट अनिश्चित काल तक `localStorage` की बदौलत कायम है, लेकिन इसका मतलब यह भी है कि यह तब तक अपडेट नहीं किया जाता जब तक आप ऐप से लॉग-आउट नहीं करते और फिर से लॉग इन नहीं करते!
यह एक खाता डेटा अपडेट करता है, फिर डैशबोर्ड पृष्ठ के HTML को अपडेट करने का ध्यान रखता है। डैशबोर्ड मार्ग लोड होने पर हमें यह कॉल करना होगा। इसके साथ रूट की परिभाषा को अपडेट करें:
अब जब हम डैशबोर्ड लोड होने के बाद हर बार खाते के डेटा को लोड करते हैं, तो क्या आपको लगता है कि हमें अभी भी *सभी खाते* डेटा को बनाए रखने की आवश्यकता है?