You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/mr/7-bank-project/4-state-management/README.md

275 lines
30 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "b46acf79da8550d76445eed00b06c878",
"translation_date": "2025-10-03T12:55:21+00:00",
"source_file": "7-bank-project/4-state-management/README.md",
"language_code": "mr"
}
-->
# बँकिंग अ‍ॅप तयार करा भाग 4: स्टेट मॅनेजमेंटची संकल्पना
## पूर्व-व्याख्यान प्रश्नमंजुषा
[पूर्व-व्याख्यान प्रश्नमंजुषा](https://ff-quizzes.netlify.app/web/quiz/47)
### परिचय
जसे जसे वेब अ‍ॅप्लिकेशन मोठे होते, तसतसे सर्व डेटा प्रवाहांचा मागोवा ठेवणे कठीण होते. कोणता कोड डेटा मिळवतो, कोणते पृष्ठ तो वापरते, तो कधी आणि कुठे अद्यतनित करायचा आहे... हे सर्व लक्षात ठेवणे कठीण होऊ शकते आणि त्यामुळे कोड गोंधळलेला आणि देखभाल करणे कठीण होतो. हे विशेषतः खरे आहे जेव्हा तुम्हाला तुमच्या अ‍ॅपच्या वेगवेगळ्या पृष्ठांमध्ये डेटा सामायिक करायचा असतो, जसे की वापरकर्त्याचा डेटा. *स्टेट मॅनेजमेंट* ही संकल्पना सर्व प्रकारच्या प्रोग्राम्समध्ये नेहमीच अस्तित्वात होती, परंतु वेब अ‍ॅप्सची जटिलता वाढत असल्याने विकासादरम्यान याचा विचार करणे महत्त्वाचे ठरते.
या अंतिम भागात, आपण तयार केलेल्या अ‍ॅपवर पुनर्विचार करू आणि स्टेट कसे व्यवस्थापित करायचे यावर लक्ष केंद्रित करू, ज्यामुळे कोणत्याही क्षणी ब्राउझर रीफ्रेशला समर्थन मिळेल आणि वापरकर्ता सत्रांमध्ये डेटा टिकवून ठेवता येईल.
### पूर्वअट
या धड्यासाठी तुम्ही [डेटा फेचिंग](../3-data/README.md) भाग पूर्ण केलेला असणे आवश्यक आहे. तुम्हाला [Node.js](https://nodejs.org) स्थापित करणे आणि [सर्व्हर API](../api/README.md) स्थानिकरित्या चालवणे आवश्यक आहे जेणेकरून तुम्ही खाते डेटा व्यवस्थापित करू शकाल.
तुम्ही टर्मिनलमध्ये हा आदेश चालवून सर्व्हर योग्यरित्या चालू आहे का ते तपासू शकता:
```sh
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
```
---
## स्टेट मॅनेजमेंटवर पुनर्विचार करा
[मागील धड्यात](../3-data/README.md), आम्ही `account` नावाच्या ग्लोबल व्हेरिएबलसह अ‍ॅपमध्ये स्टेटची मूलभूत संकल्पना सादर केली, ज्यामध्ये सध्या लॉग इन केलेल्या वापरकर्त्याचा बँक डेटा आहे. तथापि, आमच्या सध्याच्या अंमलबजावणीत काही त्रुटी आहेत. डॅशबोर्डवर असताना पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. काय होते?
सध्याच्या कोडमध्ये 3 समस्या आहेत:
- स्टेट टिकवून ठेवली जात नाही, कारण ब्राउझर रीफ्रेश केल्यावर तुम्हाला लॉगिन पृष्ठावर परत नेले जाते.
- स्टेट बदलण्यासाठी अनेक फंक्शन्स आहेत. अ‍ॅप मोठे होत असताना, बदलांचा मागोवा ठेवणे कठीण होऊ शकते आणि एखाद्या अद्यतनाची आठवण राहू शकते.
- स्टेट साफ केली जात नाही, त्यामुळे जेव्हा तुम्ही *लॉगआउट* क्लिक करता, तेव्हा लॉगिन पृष्ठावर असतानाही खाते डेटा तिथेच राहतो.
आपण या समस्यांवर एक एक करून उपाय करण्यासाठी कोड अद्यतनित करू शकतो, परंतु यामुळे कोड डुप्लिकेशन वाढेल आणि अ‍ॅप अधिक जटिल आणि देखभाल करणे कठीण होईल. किंवा आपण काही मिनिटे थांबून आपल्या रणनीतीचा पुनर्विचार करू शकतो.
> येथे आपण खरोखर कोणत्या समस्यांचे निराकरण करण्याचा प्रयत्न करत आहोत?
[स्टेट मॅनेजमेंट](https://en.wikipedia.org/wiki/State_management) म्हणजे या दोन विशिष्ट समस्यांचे निराकरण करण्यासाठी चांगला दृष्टिकोन शोधणे:
- अ‍ॅपमधील डेटा प्रवाह समजण्यासारखा कसा ठेवायचा?
- स्टेट डेटा नेहमी वापरकर्ता इंटरफेससह (आणि उलट) समक्रमित कसा ठेवायचा?
एकदा तुम्ही यांची काळजी घेतली की, तुम्हाला असलेल्या इतर कोणत्याही समस्या कदाचित आधीच निराकरण झाल्या असतील किंवा त्या सोडवणे सोपे झाले असेल. या समस्यांचे निराकरण करण्यासाठी अनेक दृष्टिकोन आहेत, परंतु आम्ही **डेटा आणि तो बदलण्याच्या पद्धती केंद्रीकृत करण्याचा** एक सामान्य उपाय निवडू. डेटा प्रवाह असा असेल:
![HTML, वापरकर्ता क्रिया आणि स्टेट यांच्यातील डेटा प्रवाह दर्शविणारी योजना](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.mr.png)
> येथे डेटा स्वयंचलितपणे दृश्य अद्यतनित करतो तो भाग आम्ही कव्हर करणार नाही, कारण तो [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) च्या अधिक प्रगत संकल्पनांशी संबंधित आहे. जर तुम्हाला सखोल अभ्यास करायचा असेल तर हा एक चांगला पुढील विषय आहे.
✅ स्टेट मॅनेजमेंटसाठी वेगवेगळ्या दृष्टिकोनांसह अनेक लायब्ररी उपलब्ध आहेत, [Redux](https://redux.js.org) हा एक लोकप्रिय पर्याय आहे. मोठ्या वेब अ‍ॅप्समध्ये तुम्ही कोणत्या संभाव्य समस्यांना सामोरे जाऊ शकता आणि त्या कशा सोडवता येतील हे शिकण्यासाठी वापरले जाणारे संकल्पना आणि पॅटर्न पाहा.
### कार्य
आम्ही थोडेसे कोड पुनर्रचना करून सुरुवात करू. `account` डिक्लेरेशन बदला:
```js
let account = null;
```
यासह:
```js
let state = {
account: null
};
```
कल्पना म्हणजे सर्व अ‍ॅप डेटा एका सिंगल स्टेट ऑब्जेक्टमध्ये *केंद्रीकृत* करणे. सध्या स्टेटमध्ये फक्त `account` आहे त्यामुळे फारसा फरक पडत नाही, परंतु भविष्यातील बदलांसाठी मार्ग तयार होतो.
आपल्याला ते वापरणाऱ्या फंक्शन्स देखील अद्यतनित कराव्या लागतील. `register()` आणि `login()` फंक्शन्समध्ये, `account = ...` ला `state.account = ...` ने बदला;
`updateDashboard()` फंक्शनच्या शीर्षस्थानी, ही ओळ जोडा:
```js
const account = state.account;
```
या पुनर्रचनेने स्वतःहून फारसे सुधारणा केल्या नाहीत, परंतु पुढील बदलांसाठी पाया घालण्याचा विचार होता.
## डेटा बदलांचा मागोवा घ्या
आता आपण डेटा साठवण्यासाठी `state` ऑब्जेक्ट तयार केला आहे, पुढील पाऊल म्हणजे अद्यतनांना केंद्रीकृत करणे. उद्दिष्ट म्हणजे कोणतेही बदल आणि ते कधी घडतात याचा मागोवा घेणे सोपे करणे.
`state` ऑब्जेक्टमध्ये बदल होऊ नयेत यासाठी, त्याला [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) मानणे चांगली पद्धत आहे, म्हणजे त्यात अजिबात बदल करता येणार नाही. याचा अर्थ असा की तुम्हाला त्यात काहीही बदल करायचे असल्यास नवीन स्टेट ऑब्जेक्ट तयार करावा लागेल. असे केल्याने, तुम्ही संभाव्य अवांछित [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) पासून संरक्षण तयार करता आणि तुमच्या अ‍ॅपमध्ये नवीन वैशिष्ट्ये अंमलात आणण्याच्या शक्यता उघडता, जसे की undo/redo अंमलात आणणे, तसेच डिबग करणे सोपे होते. उदाहरणार्थ, तुम्ही स्टेटमध्ये केलेला प्रत्येक बदल लॉग करू शकता आणि बगचा स्रोत समजण्यासाठी बदलांचा इतिहास ठेवू शकता.
JavaScript मध्ये, [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) वापरून ऑब्जेक्टची immutable आवृत्ती तयार करू शकता. जर तुम्ही immutable ऑब्जेक्टमध्ये बदल करण्याचा प्रयत्न केला, तर अपवाद निर्माण होईल.
✅ तुम्हाला *shallow* आणि *deep* immutable ऑब्जेक्टमधील फरक माहित आहे का? तुम्ही याबद्दल [येथे](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) वाचू शकता.
### कार्य
नवीन `updateState()` फंक्शन तयार करूया:
```js
function updateState(property, newData) {
state = Object.freeze({
...state,
[property]: newData
});
}
```
या फंक्शनमध्ये, आम्ही नवीन स्टेट ऑब्जेक्ट तयार करतो आणि [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) वापरून मागील स्टेटमधून डेटा कॉपी करतो. त्यानंतर आम्ही [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` वापरून स्टेट ऑब्जेक्टच्या विशिष्ट प्रॉपर्टीला नवीन डेटासह ओव्हरराइड करतो. शेवटी, `Object.freeze()` वापरून ऑब्जेक्ट लॉक करतो. सध्या स्टेटमध्ये फक्त `account` प्रॉपर्टी आहे, परंतु या दृष्टिकोनाने तुम्ही स्टेटमध्ये आवश्यक तेवढ्या प्रॉपर्टी जोडू शकता.
`state` प्रारंभिकरण देखील अद्यतनित करू जेणेकरून प्रारंभिक स्टेट देखील फ्रीज केले जाईल:
```js
let state = Object.freeze({
account: null
});
```
यानंतर, `register` फंक्शनमध्ये `state.account = result;` असाइनमेंट बदलून:
```js
updateState('account', result);
```
`login` फंक्शनमध्ये देखील तसेच करा, `state.account = data;` बदलून:
```js
updateState('account', data);
```
आता जेव्हा वापरकर्ता *Logout* क्लिक करतो तेव्हा खाते डेटा साफ न होण्याच्या समस्येचे निराकरण करण्याची संधी घेऊया.
नवीन `logout()` फंक्शन तयार करा:
```js
function logout() {
updateState('account', null);
navigate('/login');
}
```
`updateDashboard()` मध्ये, `return navigate('/login');` पुनर्निर्देशन बदलून `return logout();` करा;
नवीन खाते नोंदणी करा, लॉगआउट करा आणि पुन्हा लॉगिन करून सर्व काही योग्यरित्या कार्यरत आहे का ते तपासा.
> टीप: तुम्ही `updateState()` च्या तळाशी `console.log(state)` जोडून आणि तुमच्या ब्राउझरच्या विकास साधनांमध्ये कन्सोल उघडून सर्व स्टेट बदल पाहू शकता.
## स्टेट टिकवून ठेवा
बहुतेक वेब अ‍ॅप्सना योग्यरित्या कार्य करण्यासाठी डेटा टिकवून ठेवण्याची आवश्यकता असते. सर्व महत्त्वाचा डेटा सहसा डेटाबेसमध्ये संग्रहित केला जातो आणि सर्व्हर API द्वारे प्रवेश केला जातो, जसे की आमच्या बाबतीत वापरकर्ता खाते डेटा. परंतु कधीकधी, ब्राउझरमध्ये चालणाऱ्या क्लायंट अ‍ॅपवर काही डेटा टिकवून ठेवणे देखील मनोरंजक असते, चांगल्या वापरकर्ता अनुभवासाठी किंवा लोडिंग कार्यक्षमता सुधारण्यासाठी.
जेव्हा तुम्हाला तुमच्या ब्राउझरमध्ये डेटा टिकवून ठेवायचा असेल, तेव्हा तुम्ही स्वतःला काही महत्त्वाचे प्रश्न विचारले पाहिजेत:
- *डेटा संवेदनशील आहे का?* तुम्ही क्लायंटवर कोणताही संवेदनशील डेटा संग्रहित करणे टाळले पाहिजे, जसे की वापरकर्ता पासवर्ड.
- *तुम्हाला हा डेटा किती काळ ठेवायचा आहे?* तुम्ही हा डेटा फक्त चालू सत्रासाठी प्रवेश करण्याची योजना आखत आहात की तुम्हाला तो कायमस्वरूपी संग्रहित करायचा आहे?
वेब अ‍ॅपमध्ये माहिती संग्रहित करण्याचे अनेक मार्ग आहेत, तुम्हाला काय साध्य करायचे आहे यावर अवलंबून. उदाहरणार्थ, तुम्ही शोध क्वेरी संग्रहित करण्यासाठी URL वापरू शकता आणि ती वापरकर्त्यांमध्ये शेअर करण्यायोग्य बनवू शकता. जर डेटा सर्व्हरसह शेअर करणे आवश्यक असेल, जसे की [authentication](https://en.wikipedia.org/wiki/Authentication) माहिती, तर तुम्ही [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) वापरू शकता.
ब्राउझर API चा वापर करून डेटा संग्रहित करण्याचा आणखी एक पर्याय आहे. यापैकी दोन विशेषतः मनोरंजक आहेत:
- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): एक [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) जे सध्याच्या वेबसाइटसाठी डेटा वेगवेगळ्या सत्रांमध्ये टिकवून ठेवण्याची परवानगी देते. यात संग्रहित डेटा कधीही कालबाह्य होत नाही.
- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): हे `localStorage` प्रमाणेच कार्य करते परंतु यात संग्रहित डेटा सत्र संपल्यावर (ब्राउझर बंद केल्यावर) साफ केला जातो.
टीप की या दोन्ही API फक्त [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) साठवण्याची परवानगी देतात. जर तुम्हाला जटिल ऑब्जेक्ट्स संग्रहित करायचे असतील, तर तुम्हाला [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) वापरून ते [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) स्वरूपात सिरीयलाइझ करावे लागेल.
✅ जर तुम्हाला सर्व्हरशिवाय कार्य करणारे वेब अ‍ॅप तयार करायचे असेल, तर [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) वापरून क्लायंटवर डेटाबेस तयार करणे देखील शक्य आहे. हे प्रगत वापर प्रकरणांसाठी राखीव आहे किंवा तुम्हाला लक्षणीय प्रमाणात डेटा संग्रहित करायचा असल्यास, कारण ते वापरण्यास अधिक जटिल आहे.
### कार्य
आपण इच्छितो की आमचे वापरकर्ते *Logout* बटणावर स्पष्टपणे क्लिक करेपर्यंत लॉग इन राहावे, म्हणून आम्ही `localStorage` वापरून खाते डेटा संग्रहित करू. प्रथम, आपण डेटा संग्रहित करण्यासाठी वापरण्यासाठी एक की परिभाषित करूया.
```js
const storageKey = 'savedAccount';
```
यानंतर `updateState()` फंक्शनच्या शेवटी ही ओळ जोडा:
```js
localStorage.setItem(storageKey, JSON.stringify(state.account));
```
यामुळे, वापरकर्त्याचे खाते डेटा टिकवून ठेवले जाईल आणि आपण यापूर्वी केंद्रीकृत केलेल्या सर्व स्टेट अद्यतनांमुळे नेहमी अद्ययावत राहील. यामुळे आपल्याला केलेल्या सर्व पुनर्रचनेचा फायदा होतो 🙂.
डेटा जतन केला जात असल्याने, अ‍ॅप लोड केल्यावर तो पुनर्संचयित करण्याची देखील काळजी घ्यावी लागेल. आता आपल्याकडे अधिक प्रारंभिक कोड असणार आहे, म्हणून `init` नावाचे नवीन फंक्शन तयार करणे चांगले होईल, ज्यामध्ये `app.js` च्या तळाशी असलेला आपला पूर्वीचा कोड देखील समाविष्ट असेल:
```js
function init() {
const savedAccount = localStorage.getItem(storageKey);
if (savedAccount) {
updateState('account', JSON.parse(savedAccount));
}
// Our previous initialization code
window.onpopstate = () => updateRoute();
updateRoute();
}
init();
```
येथे आम्ही जतन केलेला डेटा पुनर्प्राप्त करतो आणि जर काही डेटा सापडला तर आम्ही त्यानुसार स्टेट अद्यतनित करतो. हे *रूट* अद्यतनित करण्यापूर्वी करणे महत्त्वाचे आहे, कारण पृष्ठ अद्यतनादरम्यान स्टेटवर अवलंबून असलेला कोड असू शकतो.
आता आपण *Dashboard* पृष्ठाला आपल्या अ‍ॅप्लिकेशनचे डिफॉल्ट पृष्ठ बनवू शकतो, कारण आपण आता खाते डेटा टिकवून ठेवत आहोत. जर कोणताही डेटा सापडला नाही, तर डॅशबोर्ड *Login* पृष्ठावर पुनर्निर्देशित करण्याची काळजी घेतो. `updateRoute()` मध्ये, फॉलबॅक `return navigate('/login');` बदलून `return navigate('/dashboard');` करा.
आता अ‍ॅपमध्ये लॉगिन करा आणि पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. तुम्ही डॅशबोर्डवरच राहाल. या अद्यतनासह आपण आपल्या सर्व प्रारंभिक समस्यांचे निराकरण केले आहे...
## डेटा रीफ्रेश करा
...पण आपण नवीन समस्या निर्माण केली असू शकतो. ओह!
`test` खाते वापरून डॅशबोर्डवर जा, नंतर टर्मिनलवर हा आदेश चालवून नवीन व्यवहार तयार करा:
```sh
curl --request POST \
--header "Content-Type: application/json" \
--data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
http://localhost:5000/api/accounts/test/transactions
```
आता ब्राउझरमध्ये तुमचे डॅशबोर्ड पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. काय होते? तुम्हाला नवीन व्यवहार दिसतो का?
`localStorage` मुळे स्टेट अनिश्चित काळासाठी टिकवून ठेवली जाते, परंतु याचा अर्थ असा आहे की तुम्ही अ‍ॅपमधून लॉगआउट आणि पुन्हा लॉगिन केल्याशिवाय ती कधीही अद्यतनित होत नाही!
हे टाळण्यासाठी एक संभाव्य रणनीती म्हणजे डॅशबोर्ड लोड केल्यावर प्रत्येक वेळी खाते डेटा पुन्हा लोड करणे, जेणेकरून डेटा जुना होणार नाही.
### कार्य
नवीन `updateAccountData` फंक्शन तयार करा:
```js
async function updateAccountData() {
const account = state.account;
if (!account) {
return logout();
}
const data = await getAccount(account.user);
if (data.error) {
return logout();
}
updateState('account', data);
}
```
हे फंक्शन तपासते की आपण सध्या लॉग इन आहोत आणि नंतर सर्व्हरवरून खाते डेटा पुन्हा लोड करते.
`refresh` नावाचे आणखी एक फंक्शन तयार करा:
```js
async function refresh() {
await updateAccountData();
updateDashboard();
}
```
हे खाते डेटा अद्यतनित करते, नंतर डॅशबोर्ड पृष्ठाच्या HTML चे अद्यतनित करण्याची काळजी घेते. डॅशबोर्ड रूट लोड झाल्यावर आम्हाला कॉल करायचे आहे तेच आहे. रूट
[व्याख्यानानंतरचा प्रश्नमंजूषा](https://ff-quizzes.netlify.app/web/quiz/48)
## असाइनमेंट
["Add transaction" संवाद लागू करा](assignment.md)
असाइनमेंट पूर्ण केल्यानंतरचा एक उदाहरण परिणाम येथे दिला आहे:
!["Add transaction" संवादाचे उदाहरण स्क्रीनशॉट दाखवत आहे](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.mr.png)
---
**अस्वीकरण**:
हा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपयास लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून निर्माण होणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.