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/ne/7-bank-project/4-state-management
softchris 04881ec984
🌐 Update translations via Co-op Translator
10 months ago
..
README.md 🌐 Update translations via Co-op Translator 10 months ago
assignment.md 🌐 Update translations via Co-op Translator 12 months ago

README.md

बैंकिङ एप निर्माण भाग ४: स्टेट म्यानेजमेन्टको अवधारणा

प्रि-लेक्चर क्विज

प्रि-लेक्चर क्विज

परिचय

जसरी वेब एप्लिकेसन बढ्दै जान्छ, सबै डाटा प्रवाहलाई ट्र्याक गर्नु चुनौतीपूर्ण हुन्छ। कुन कोडले डाटा प्राप्त गर्छ, कुन पेजले यसलाई प्रयोग गर्छ, कहिले र कहाँ यसलाई अपडेट गर्नुपर्छ... यसले सजिलैसँग जटिल कोड सिर्जना गर्न सक्छ जुन मर्मत गर्न गाह्रो हुन्छ। यो विशेष गरी सत्य हो जब तपाईंलाई एपका विभिन्न पेजहरूमा डाटा साझा गर्न आवश्यक हुन्छ, जस्तै प्रयोगकर्ता डाटा। स्टेट म्यानेजमेन्ट को अवधारणा सबै प्रकारका प्रोग्रामहरूमा सधैं रहेको छ, तर वेब एपहरू जटिलतामा बढ्दै जाँदा यो विकासको क्रममा सोच्नुपर्ने मुख्य बिन्दु बनेको छ।

यस अन्तिम भागमा, हामीले बनाएको एपलाई पुनः हेर्नेछौं ताकि स्टेटलाई व्यवस्थापन गर्ने तरिका सुधार गर्न सकियोस्, जसले ब्राउजर रिफ्रेसलाई कुनै पनि समयमा समर्थन गर्न र प्रयोगकर्ता सत्रहरूमा डाटा कायम राख्न अनुमति दिन्छ।

पूर्व-आवश्यकता

यस पाठको लागि तपाईंले वेब एपको डाटा फेचिङ भाग पूरा गरिसक्नुपर्छ। तपाईंले Node.js स्थापना गर्नुपर्छ र सर्भर API चलाउनुहोस् ताकि तपाईं खाता डाटा व्यवस्थापन गर्न सक्नुहुन्छ।

तपाईंले सर्भर ठीकसँग चलिरहेको छ कि छैन जाँच गर्न टर्मिनलमा यो कमाण्ड चलाउन सक्नुहुन्छ:

curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result

स्टेट म्यानेजमेन्ट पुनः विचार गर्नुहोस्

अघिल्लो पाठ मा, हामीले हाम्रो एपमा स्टेटको आधारभूत अवधारणा प्रस्तुत गर्यौं, जसमा account नामक ग्लोबल भेरिएबलले हालको लगइन प्रयोगकर्ताको बैंक डाटा समावेश गर्दछ। तर, हाम्रो हालको कार्यान्वयनमा केही कमजोरीहरू छन्। ड्यासबोर्डमा हुँदा पेज रिफ्रेस गर्नुहोस्। के हुन्छ?

हालको कोडमा तीन समस्या छन्:

  • स्टेट कायम छैन, किनकि ब्राउजर रिफ्रेसले तपाईंलाई लगइन पेजमा फर्काउँछ।
  • स्टेटलाई परिवर्तन गर्ने धेरै फङ्सनहरू छन्। एप बढ्दै जाँदा, यसले परिवर्तनहरू ट्र्याक गर्न गाह्रो बनाउँछ र एउटा अपडेट गर्न बिर्सन सजिलो हुन्छ।
  • स्टेट सफा गरिएको छैन, त्यसैले जब तपाईं Logout क्लिक गर्नुहुन्छ, खाता डाटा अझै त्यहाँ हुन्छ, यद्यपि तपाईं लगइन पेजमा हुनुहुन्छ।

हामी यी समस्याहरूलाई एक-एक गरेर समाधान गर्न कोड अपडेट गर्न सक्थ्यौं, तर यसले कोड दोहोर्याउने र एपलाई अझ जटिल र मर्मत गर्न गाह्रो बनाउनेछ। वा हामी केही मिनेटको लागि रोक्न सक्छौं र हाम्रो रणनीति पुनः विचार गर्न सक्छौं।

यहाँ हामी वास्तवमा के समस्या समाधान गर्न खोज्दैछौं?

स्टेट म्यानेजमेन्ट भनेको यी दुई विशेष समस्याहरू समाधान गर्न राम्रो दृष्टिकोण खोज्नु हो:

  • एपमा डाटा प्रवाहलाई कसरी बुझ्न सकिने बनाउने?
  • स्टेट डाटालाई सधैं प्रयोगकर्ता इन्टरफेससँग (र उल्टो) कसरी सिंकमा राख्ने?

यी समस्याहरू समाधान गरेपछि, तपाईंले सामना गर्न सक्ने अन्य समस्याहरू या त पहिले नै समाधान भएका छन् वा समाधान गर्न सजिलो भएका छन्। यी समस्याहरू समाधान गर्न धेरै सम्भावित दृष्टिकोणहरू छन्, तर हामी डाटा र यसलाई परिवर्तन गर्ने तरिकाहरूलाई केन्द्रित गर्ने सामान्य समाधानको साथ जानेछौं। डाटा प्रवाह यसरी जानेछ:

HTML, प्रयोगकर्ता क्रियाकलाप र स्टेट बीचको डाटा प्रवाह देखाउने स्कीमा

यहाँ हामी डाटाले दृश्य अपडेटलाई स्वतः ट्रिगर गर्ने भागलाई कभर गर्ने छैनौं, किनकि यो Reactive Programming को थप उन्नत अवधारणासँग सम्बन्धित छ। यदि तपाईं गहिरो अध्ययन गर्न इच्छुक हुनुहुन्छ भने यो राम्रो विषय हो।

त्यहाँ स्टेट म्यानेजमेन्टका विभिन्न दृष्टिकोणहरू भएका धेरै लाइब्रेरीहरू छन्, Redux एक लोकप्रिय विकल्प हो। यसमा प्रयोग गरिएका अवधारणाहरू र ढाँचाहरू हेर्नुहोस् किनकि यो ठूलो वेब एपहरूमा तपाईंले सामना गर्न सक्ने सम्भावित समस्याहरू र यसलाई कसरी समाधान गर्न सकिन्छ भन्ने सिक्ने राम्रो तरिका हो।

कार्य

हामी थोरै रिफ्याक्टरिङबाट सुरु गर्नेछौं। account घोषणा प्रतिस्थापन गर्नुहोस्:

let account = null;

यससँग:

let state = {
  account: null
};

विचार भनेको हाम्रो एप डाटालाई एकल स्टेट वस्तुमा केन्द्रित गर्नु हो। अहिले स्टेटमा केवल account छ, त्यसैले यसले धेरै परिवर्तन गर्दैन, तर यसले विकासको लागि मार्ग बनाउँछ।

हामीले यसलाई प्रयोग गर्ने फङ्सनहरू पनि अपडेट गर्नुपर्छ। register()login() फङ्सनहरूमा, account = ... लाई state.account = ... ले प्रतिस्थापन गर्नुहोस्;

updateDashboard() फङ्सनको शीर्षमा, यो लाइन थप्नुहोस्:

const account = state.account;

यो रिफ्याक्टरिङले आफैंमा धेरै सुधार ल्याएन, तर विचार भनेको आगामी परिवर्तनहरूको लागि आधार तयार गर्नु हो।

डाटा परिवर्तनहरू ट्र्याक गर्नुहोस्

अब हामीले हाम्रो डाटा भण्डारण गर्न state वस्तु राखेका छौं, अर्को चरण भनेको अपडेटहरू केन्द्रित गर्नु हो। लक्ष्य भनेको कुनै पनि परिवर्तनहरू र तिनीहरू कहिले हुन्छन् भनेर ट्र्याक गर्न सजिलो बनाउनु हो।

state वस्तुमा परिवर्तनहरू गर्नबाट बच्न, यसलाई immutable मान्नु राम्रो अभ्यास हो, जसको अर्थ यो बिल्कुलै परिवर्तन गर्न सकिँदैन। यसको मतलब तपाईंले यसमा केही परिवर्तन गर्न चाहनुहुन्छ भने नयाँ स्टेट वस्तु सिर्जना गर्नुपर्छ। यसो गर्दा, तपाईंले सम्भावित अवाञ्छित साइड इफेक्टहरू को बारेमा सुरक्षा निर्माण गर्नुहुन्छ, र तपाईंको एपमा नयाँ सुविधाहरू कार्यान्वयन गर्ने सम्भावनाहरू खोल्नुहुन्छ जस्तै undo/redo कार्यान्वयन गर्नु, साथै डिबग गर्न सजिलो बनाउनु। उदाहरणका लागि, तपाईंले स्टेटमा गरिएका प्रत्येक परिवर्तनलाई लग गर्न सक्नुहुन्छ र बगको स्रोत बुझ्न परिवर्तनहरूको इतिहास राख्न सक्नुहुन्छ।

JavaScript मा, तपाईं Object.freeze() प्रयोग गरेर वस्तुको अपरिवर्तनीय संस्करण सिर्जना गर्न सक्नुहुन्छ। यदि तपाईंले अपरिवर्तनीय वस्तुमा परिवर्तन गर्न प्रयास गर्नुभयो भने, एक अपवाद उठाइनेछ।

shallowdeep अपरिवर्तनीय वस्तु बीचको भिन्नता के हो? तपाईं यसबारे यहाँ पढ्न सक्नुहुन्छ।

कार्य

नयाँ updateState() फङ्सन सिर्जना गरौं:

function updateState(property, newData) {
  state = Object.freeze({
    ...state,
    [property]: newData
  });
}

यस फङ्सनमा, हामी नयाँ स्टेट वस्तु सिर्जना गर्दैछौं र spread (...) operator प्रयोग गरेर अघिल्लो स्टेटबाट डाटा प्रतिलिपि गर्दैछौं। त्यसपछि हामी bracket notation [property] प्रयोग गरेर स्टेट वस्तुको विशेष सम्पत्तिलाई नयाँ डाटासँग ओभरराइड गर्छौं। अन्तमा, हामी Object.freeze() प्रयोग गरेर वस्तुलाई परिवर्तनहरू रोक्न लक गर्छौं। अहिले स्टेटमा account सम्पत्ति मात्र भण्डारण गरिएको छ, तर यस दृष्टिकोणले तपाईंलाई स्टेटमा आवश्यक जति सम्पत्तिहरू थप्न अनुमति दिन्छ।

हामीले स्टेटको सुरुवात पनि अपडेट गर्नुपर्छ ताकि प्रारम्भिक स्टेट पनि फ्रिज गरिएको हो:

let state = Object.freeze({
  account: null
});

त्यसपछि, register फङ्सनलाई state.account = result; असाइनमेन्टलाई प्रतिस्थापन गरेर अपडेट गर्नुहोस्:

updateState('account', result);

login फङ्सनमा पनि त्यस्तै गर्नुहोस्, state.account = data; लाई प्रतिस्थापन गरेर:

updateState('account', data);

अब हामी Logout क्लिक गर्दा खाता डाटा सफा नगरिएको समस्यालाई समाधान गर्ने मौका लिन्छौं।

नयाँ logout() फङ्सन सिर्जना गर्नुहोस्:

function logout() {
  updateState('account', null);
  navigate('/login');
}

updateDashboard() मा, return navigate('/login'); रिडिरेक्शनलाई return logout(); ले प्रतिस्थापन गर्नुहोस्;

नयाँ खाता दर्ता गर्ने प्रयास गर्नुहोस्, लगआउट र फेरि लगइन गरेर सबै ठीकसँग काम गरिरहेको छ कि छैन जाँच गर्नुहोस्।

टिप: तपाईंले updateState() को तल console.log(state) थपेर र आफ्नो ब्राउजरको विकास उपकरणमा कन्सोल खोलेर सबै स्टेट परिवर्तनहरू हेर्न सक्नुहुन्छ।

स्टेटलाई कायम राख्नुहोस्

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

जब तपाईं आफ्नो ब्राउजरमा डाटा कायम राख्न चाहनुहुन्छ, त्यहाँ केही महत्त्वपूर्ण प्रश्नहरू छन् जुन तपाईंले आफैंलाई सोध्नुपर्छ:

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

वेब एप भित्र जानकारी भण्डारण गर्ने धेरै तरिकाहरू छन्, तपाईं के हासिल गर्न चाहनुहुन्छ भन्ने कुरामा निर्भर गर्दै। उदाहरणका लागि, तपाईंले खोज क्वेरी भण्डारण गर्न URL प्रयोग गर्न सक्नुहुन्छ, र यसलाई प्रयोगकर्ताहरू बीच साझा गर्न सक्नुहुन्छ। तपाईंले HTTP कुकीहरू पनि प्रयोग गर्न सक्नुहुन्छ यदि डाटालाई सर्भरसँग साझा गर्न आवश्यक छ भने, जस्तै प्रमाणीकरण जानकारी।

अर्को विकल्प भनेको डाटा भण्डारण गर्न ब्राउजर API हरू मध्ये एक प्रयोग गर्नु हो। दुई विशेष रूपमा रोचक छन्:

  • localStorage: एक Key/Value store जसले विभिन्न सत्रहरूमा हालको वेबसाइटको लागि विशिष्ट डाटा कायम राख्न अनुमति दिन्छ। यसमा भण्डारण गरिएको डाटा कहिल्यै समाप्त हुँदैन।
  • sessionStorage: यो localStorage जस्तै काम गर्छ तर यसमा भण्डारण गरिएको डाटा सत्र समाप्त हुँदा (ब्राउजर बन्द हुँदा) सफा गरिन्छ।

ध्यान दिनुहोस् कि यी दुवै API ले केवल strings भण्डारण गर्न अनुमति दिन्छ। यदि तपाईंले जटिल वस्तुहरू भण्डारण गर्न चाहनुहुन्छ भने, तपाईंले यसलाई JSON ढाँचामा सिरियलाइज गर्नुपर्नेछ JSON.stringify() प्रयोग गरेर।

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

कार्य

हामी चाहन्छौं कि हाम्रो प्रयोगकर्ताहरू स्पष्ट रूपमा Logout बटन क्लिक नगरेसम्म लगइन रहून्, त्यसैले हामी localStorage प्रयोग गरेर खाता डाटा भण्डारण गर्नेछौं। पहिलो, हामीले डाटा भण्डारण गर्न प्रयोग गर्ने कुञ्जी परिभाषित गरौं।

const storageKey = 'savedAccount';

त्यसपछि updateState() फङ्सनको अन्त्यमा यो लाइन थप्नुहोस्:

localStorage.setItem(storageKey, JSON.stringify(state.account));

यससँग, प्रयोगकर्ता खाता डाटा कायम हुनेछ र हामीले पहिले केन्द्रित गरेका सबै स्टेट अपडेटहरू जस्तै सधैं अद्यावधिक हुनेछ। यहीँबाट हामीले हाम्रो अघिल्लो रिफ्याक्टरहरूबाट लाभ लिन सुरु गर्छौं 🙂

जसरी डाटा बचत गरिएको छ, हामीले एप लोड हुँदा यसलाई पुनःस्थापित गर्न पनि ध्यान दिनुपर्छ। किनकि हामीसँग पहिलेको कोडको थप सुरुवात कोड हुन थाल्छ, नयाँ init फङ्सन सिर्जना गर्नु राम्रो विचार हुन सक्छ, जसले app.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 खाता प्रयोग गरेर ड्यासबोर्डमा जानुहोस्, त्यसपछि नयाँ ट्रान्जेक्सन सिर्जना गर्न टर्मिनलमा यो कमाण्ड चलाउनुहोस्:

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 फङ्सन सिर्जना गर्नुहोस्:

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 नामक अर्को फङ्सन सिर्जना गर्नुहोस्:

async function refresh() {
  await updateAccountData();
  updateDashboard();
}

यसले खाता डाटा अपडेट गर्छ, त्यसपछि ड्यासबोर्ड पेजको HTML अपडेट गर्न ख्याल राख्छ। यो ड्यासबोर्ड रुट लोड हुँदा हामीले कल गर्न आवश्यक छ। रुट परिभाषा अपडेट गर्नुहोस्:

const routes = {
  '/login': { templateId: 'login' },
  '/dashboard': { templateId: 'dashboard', init: refresh }
};

अब ड्यासबोर्ड रिफ्रेस गर्ने प्रयास गर्नुहोस्, यसले अपडेट गरिएको खाता डाटा देखाउनु पर्छ।

GitHub Copilot Agent Challenge 🚀

Agent मोड प्रयोग गरेर निम्न चुनौती पूरा गर्नुहोस्:

विवरण: बैंकिङ एपका लागि undo/redo कार्यक्षमता सहित व्यापक स्टेट म्यानेजमेन्ट प्रणाली कार्यान्वयन गर्नुहोस्। यो चुनौतीले तपाईंलाई उन्नत स्टेट म्यानेजमेन्ट अवधारणाहरू अभ्यास गर्न मद्दत गर्नेछ जसमा स्टेट इतिहास ट्र्याकिङ, अपरिवर्तनीय अपडेटहरू, र प्रयोगकर्ता इन्टरफेस सिंक्रोनाइजेसन समावेश छ। प्रारम्भिक: सुधारिएको राज्य व्यवस्थापन प्रणाली बनाउनुहोस् जसमा समावेश छन्: 1) राज्य इतिहास एरे जसले सबै अघिल्लो अवस्थाहरू ट्र्याक गर्दछ, 2) Undo र redo कार्यहरू जसले अघिल्लो अवस्थाहरूमा फर्कन सक्छ, 3) ड्यासबोर्डमा undo/redo अपरेशनहरूको लागि UI बटनहरू, 4) मेमोरी समस्याहरू रोक्नको लागि १० अवस्थाको अधिकतम इतिहास सीमा, र 5) प्रयोगकर्ता बाहिर निस्कँदा इतिहासको उचित सफाइ। सुनिश्चित गर्नुहोस् कि undo/redo कार्यक्षमता खाता ब्यालेन्स परिवर्तनहरूसँग काम गर्दछ र ब्राउजर रिफ्रेस हुँदा पनि कायम रहन्छ।

🚀 चुनौती

अब हामीले ड्यासबोर्ड लोड हुँदा खाता डेटा पुनः लोड गर्ने गरेका छौं, के तपाईंलाई लाग्छ कि हामीले सबै खाता डेटा कायम राख्न अझै आवश्यक छ?

localStorage मा के बचत गर्ने र लोड गर्ने परिवर्तन गर्न प्रयास गर्नुहोस् ताकि एपलाई काम गर्नको लागि मात्र आवश्यक कुरा समावेश होस्।

पोस्ट-व्याख्यान क्विज

पोस्ट-व्याख्यान क्विज

असाइनमेन्ट

"Add transaction" संवाद लागू गर्नुहोस्

असाइनमेन्ट पूरा गरेपछि यहाँ एउटा उदाहरण परिणाम छ:

Screenshot showing an example "Add transaction" dialog


अस्वीकरण:
यो दस्तावेज AI अनुवाद सेवा Co-op Translator प्रयोग गरेर अनुवाद गरिएको छ। हामी शुद्धताको लागि प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छ। यसको मूल भाषा मा रहेको मूल दस्तावेजलाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीको लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुनेछैनौं।