diff --git a/translations/ar/7-bank-project/4-state-management/README.md b/translations/ar/7-bank-project/4-state-management/README.md index 123807a34..da756a252 100644 --- a/translations/ar/7-bank-project/4-state-management/README.md +++ b/translations/ar/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Създаване на Банкова Приложение Част 4: Концепции за Управление на Състоянието +# Създаване на банково приложение, част 4: Концепции за управление на състоянието -## Предварителен Тест +## Предварителен тест [Предварителен тест](https://ff-quizzes.netlify.app/web/quiz/47) ### Въведение -С разрастването на уеб приложението става предизвикателство да се следят всички потоци от данни. Кой код получава данните, коя страница ги използва, къде и кога трябва да бъдат актуализирани... лесно е да се стигне до объркан код, който е труден за поддръжка. Това е особено вярно, когато трябва да споделяте данни между различни страници на приложението, например данни за потребителя. Концепцията за *управление на състоянието* винаги е съществувала във всякакви програми, но с нарастващата сложност на уеб приложенията тя вече е ключова точка за обмисляне по време на разработката. +С разрастването на уеб приложението става предизвикателство да се следят всички потоци от данни. Кой код получава данните, коя страница ги използва, къде и кога трябва да бъдат актуализирани... лесно е да се стигне до объркан код, който е труден за поддръжка. Това е особено вярно, когато трябва да споделяте данни между различни страници на приложението си, например данни за потребителя. Концепцията за *управление на състоянието* винаги е съществувала във всички видове програми, но с нарастващата сложност на уеб приложенията тя вече е ключова точка за обмисляне по време на разработката. В тази последна част ще разгледаме приложението, което създадохме, за да преосмислим как се управлява състоянието, като позволим поддръжка на обновяване на браузъра във всеки момент и запазване на данните между потребителските сесии. @@ -51,11 +51,11 @@ curl http://localhost:5000/api - Как да направим потоците от данни в приложението разбираеми? - Как да поддържаме данните за състоянието винаги синхронизирани с потребителския интерфейс (и обратно)? -След като се погрижите за тези проблеми, всички други проблеми, които може да имате, или ще бъдат вече решени, или ще станат по-лесни за решаване. Има много възможни подходи за решаване на тези проблеми, но ние ще използваме общо решение, което се състои в **централизиране на данните и начините за тяхната промяна**. Потокът от данни би изглеждал така: +След като се погрижите за тези проблеми, всички други проблеми, които може да имате, може вече да са решени или да са станали по-лесни за решаване. Има много възможни подходи за решаване на тези проблеми, но ще използваме общо решение, което се състои в **централизиране на данните и начините за тяхната промяна**. Потокът от данни би изглеждал така: ![Схема, показваща потоците от данни между HTML, действията на потребителя и състоянието](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.bg.png) -> Тук няма да разглеждаме частта, където данните автоматично задействат актуализацията на изгледа, тъй като тя е свързана с по-напреднали концепции на [Реактивното програмиране](https://en.wikipedia.org/wiki/Reactive_programming). Това е добра тема за последващо задълбочено изучаване. +> Тук няма да разглеждаме частта, в която данните автоматично задействат актуализацията на изгледа, тъй като тя е свързана с по-напреднали концепции на [Реактивното програмиране](https://en.wikipedia.org/wiki/Reactive_programming). Това е добра тема за последващо задълбочаване. ✅ Има много библиотеки с различни подходи за управление на състоянието, като [Redux](https://redux.js.org) е популярна опция. Разгледайте концепциите и моделите, които се използват, тъй като често е добър начин да научите какви потенциални проблеми може да срещнете в големи уеб приложения и как те могат да бъдат решени. @@ -91,7 +91,7 @@ const account = state.account; Сега, когато сме поставили обекта `state`, за да съхраняваме данните си, следващата стъпка е да централизиране актуализациите. Целта е да се улесни проследяването на всякакви промени и кога те се случват. -За да избегнем промени в обекта `state`, също е добра практика да го считаме за [*неизменяем*](https://en.wikipedia.org/wiki/Immutable_object), което означава, че той изобщо не може да бъде модифициран. Това също означава, че трябва да създадете нов обект за състояние, ако искате да промените нещо в него. Като правите това, изграждате защита срещу потенциално нежелани [странични ефекти](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) и отваряте възможности за нови функции в приложението си, като например внедряване на undo/redo, като същевременно улеснявате дебъгването. Например, можете да регистрирате всяка промяна, направена в състоянието, и да запазите история на промените, за да разберете източника на грешка. +За да избегнем промени в обекта `state`, също е добра практика да го считаме за [*неизменяем*](https://en.wikipedia.org/wiki/Immutable_object), което означава, че той не може да бъде модифициран изобщо. Това също означава, че трябва да създадете нов обект за състояние, ако искате да промените нещо в него. Като правите това, изграждате защита срещу потенциално нежелани [странични ефекти](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), за да създадете неизменяема версия на обект. Ако се опитате да направите промени в неизменяем обект, ще бъде хвърлено изключение. @@ -112,7 +112,7 @@ function updateState(property, newData) { В тази функция създаваме нов обект за състояние и копираме данни от предишното състояние, използвайки [*оператора за разпръскване (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). След това презаписваме конкретно свойство на обекта за състояние с новите данни, използвайки [нотацията с квадратни скоби](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` за присвояване. Накрая заключваме обекта, за да предотвратим модификации, използвайки `Object.freeze()`. Засега имаме само свойството `account`, съхранено в състоянието, но с този подход можете да добавите толкова свойства, колкото са ви необходими. -Също така ще актуализираме инициализацията на `state`, за да се уверим, че началното състояние също е заключено: +Също така ще актуализираме инициализацията на `state`, за да сме сигурни, че началното състояние също е заключено: ```js let state = Object.freeze({ @@ -147,31 +147,31 @@ function logout() { Опитайте да регистрирате нов акаунт, да излезете и да влезете отново, за да проверите дали всичко все още работи правилно. -> Съвет: можете да разгледате всички промени в състоянието, като добавите `console.log(state)` в края на `updateState()` и отворите конзолата в инструментите за разработка на браузъра. +> Съвет: можете да разгледате всички промени в състоянието, като добавите `console.log(state)` в края на `updateState()` и отворите конзолата в инструментите за разработка на браузъра си. ## Запазване на състоянието -Повечето уеб приложения трябва да запазват данни, за да могат да работят правилно. Всички критични данни обикновено се съхраняват в база данни и се достъпват чрез API сървър, като например данните за потребителския акаунт в нашия случай. Но понякога е интересно да се запазят някои данни в клиентското приложение, което работи в браузъра, за по-добро потребителско изживяване или за подобряване на производителността при зареждане. +Повечето уеб приложения трябва да запазват данни, за да могат да работят правилно. Всички критични данни обикновено се съхраняват в база данни и се достъпват чрез API на сървъра, като например данните за потребителския акаунт в нашия случай. Но понякога е интересно да се запазят някои данни в клиентското приложение, което работи в браузъра, за по-добро потребителско изживяване или за подобряване на производителността при зареждане. -Когато искате да запазите данни в браузъра, има няколко важни въпроса, които трябва да си зададете: +Когато искате да запазите данни в браузъра си, има няколко важни въпроса, които трябва да си зададете: - *Данните чувствителни ли са?* Трябва да избягвате съхраняването на чувствителни данни в клиента, като например пароли на потребители. -- *За колко време трябва да запазите тези данни?* Планирате ли да достъпите тези данни само за текущата сесия или искате те да бъдат съхранени завинаги? +- *Колко дълго трябва да запазите тези данни?* Планирате ли да достъпвате тези данни само за текущата сесия или искате те да бъдат съхранени завинаги? -Има множество начини за съхраняване на информация в уеб приложение, в зависимост от това, което искате да постигнете. Например, можете да използвате URL адресите, за да съхранявате заявка за търсене и да я направите споделима между потребителите. Можете също така да използвате [HTTP бисквитки](https://developer.mozilla.org/docs/Web/HTTP/Cookies), ако данните трябва да бъдат споделени със сървъра, като информация за [автентикация](https://en.wikipedia.org/wiki/Authentication). +Има множество начини за съхраняване на информация в уеб приложение, в зависимост от това, което искате да постигнете. Например, можете да използвате URL адресите, за да съхранявате заявка за търсене и да я направите споделима между потребителите. Можете също така да използвате [HTTP бисквитки](https://developer.mozilla.org/docs/Web/HTTP/Cookies), ако данните трябва да бъдат споделени със сървъра, като например информация за [автентикация](https://en.wikipedia.org/wiki/Authentication). -Друга опция е да използвате една от многото API на браузъра за съхраняване на данни. Две от тях са особено интересни: +Друга опция е да използвате един от многото API на браузъра за съхраняване на данни. Два от тях са особено интересни: - [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Key/Value хранилище](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), което позволява запазване на данни, специфични за текущия уеб сайт, между различни сесии. Данните, запазени в него, никога не изтичат. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): работи по същия начин като `localStorage`, с изключение на това, че данните, съхранени в него, се изчистват, когато сесията приключи (когато браузърът се затвори). Имайте предвид, че и двата API позволяват съхраняване само на [стрингове](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Ако искате да съхранявате сложни обекти, ще трябва да ги сериализирате във формат [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON), използвайки [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Ако искате да създадете уеб приложение, което не работи със сървър, е възможно да създадете база данни на клиента, използвайки API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Това е запазено за напреднали случаи на употреба или ако трябва да съхранявате значително количество данни, тъй като е по-сложно за използване. +✅ Ако искате да създадете уеб приложение, което не работи със сървър, е възможно да създадете база данни на клиента, използвайки [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Това е запазено за напреднали случаи на употреба или ако трябва да съхранявате значително количество данни, тъй като е по-сложно за използване. ### Задача -Искаме нашите потребители да останат влезли, докато не кликнат изрично върху бутона *Изход*, така че ще използваме `localStorage`, за да съхраняваме данните за акаунта. Първо, нека дефинираме ключ, който ще използваме за съхраняване на нашите данни. +Искаме нашите потребители да останат влезли, докато не кликнат изрично върху бутона *Изход*, затова ще използваме `localStorage`, за да съхраняваме данните за акаунта. Първо, нека дефинираме ключ, който ще използваме за съхраняване на данните. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -С това данните за потребителския акаунт ще бъдат запазени и винаги актуални, както централизирахме преди всички актуализации на състоянието. Тук започваме да се възползваме от всички предишни рефакторирания 🙂. +С това данните за потребителския акаунт ще бъдат запазени и винаги актуални, тъй като преди това централизирахме всички актуализации на състоянието. Тук започваме да се възползваме от всички предишни рефакторирания 🙂. -Тъй като данните се запазват, трябва също да се погрижим за тяхното възстановяване, когато приложението се зареди. Тъй като ще започнем да имаме повече код за инициализация, може би е добра идея да създадем нова функция `init`, която също включва предишния код в края на `app.js`: +Тъй като данните се запазват, трябва също да се погрижим за тяхното възстановяване, когато приложението се зареди. Тъй като започваме да имаме повече код за инициализация, може би е добра идея да създадем нова функция `init`, която включва и предишния код в края на `app.js`: ```js function init() { @@ -204,13 +204,13 @@ init(); Тук извличаме запазените данни и ако има такива, актуализираме състоянието съответно. Важно е да направим това *преди* актуализирането на маршрута, тъй като може да има код, който разчита на състоянието по време на актуализацията на страницата. -Също така можем да направим страницата *Табло* основната страница на нашето приложение, тъй като сега запазваме данните за акаунта. Ако не се намерят данни, таблото се грижи за пренасочването към страницата *Вход* така или иначе. В `updateRoute()` заменете резервния `return navigate('/login');` с `return navigate('/dashboard');`. +Също така можем да направим страницата *Табло* основната страница на нашето приложение, тъй като сега запазваме данните за акаунта. Ако не се намерят данни, таблото се грижи за пренасочването към страницата *Вход* така или иначе. В `updateRoute()` заменете резервния вариант `return navigate('/login');` с `return navigate('/dashboard');`. Сега влезте в приложението и опитайте да обновите страницата. Трябва да останете на таблото. С тази актуализация сме се погрижили за всички първоначални проблеми... ## Обновяване на данните -...Но може би сме създали нов проблем. Опа! +...Но може би сме създали нов. Опа! Отидете на таблото, използвайки акаунта `test`, след това изпълнете тази команда в терминала, за да създадете нова транзакция: @@ -223,7 +223,7 @@ curl --request POST \ Опитайте да обновите страницата на таблото в браузъра сега. Какво се случва? Виждате ли новата транзакция? -Състоянието се запазва безкрайно благодарение на `localStorage`, но това също означава, че то никога не се актуализира, докато не излезете от приложението и не влезете отново! +Състоянието се запазва безкрайно благодарение на `localStorage`, но това също означава, че никога не се актуализира, докато не излезете от приложението и не влезете отново! Една възможна стратегия за решаване на този проблем е да презареждаме данните за акаунта всеки път, когато таблото се зарежда, за да избегнем остарели данни. @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Този метод проверява дали в момента сме влезли, след това презарежда данните за акаунта от сървъра. +Този метод проверява дали в момента сме влезли, след което презарежда данните за акаунта от сървъра. Създайте друга функция, наречена `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Тази функция актуализира данните за акаунта, след това се грижи за актуализирането на HTML на страницата на таблото. Това е, което трябва да извикаме, когато маршрутът на таблото се зареди. Актуализирайте дефиницията на маршрута с: +Тази функция актуализира данните за акаунта, след което се грижи за актуализирането на HTML на страницата на таблото. Това е, което трябва да извикаме, когато маршрутът на таблото се зареди. Актуализирайте дефиницията на маршрута с: ```js const routes = { @@ -268,13 +268,17 @@ const routes = { ``` Опитайте да обновите таблото сега, то трябва да показва актуализираните данни за акаунта -[Реализиране на диалог "Добавяне на транзакция"](assignment.md) +[Тест след лекцията](https://ff-quizzes.netlify.app/web/quiz/48) -Ето примерен резултат след завършване на задачата: +## Задание -![Екранна снимка, показваща примерен диалог "Добавяне на транзакция"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.bg.png) +[Реализирайте диалогов прозорец "Добавяне на транзакция"](assignment.md) + +Ето примерен резултат след изпълнение на заданието: + +![Екранна снимка, показваща примерен диалогов прозорец "Добавяне на транзакция"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.bg.png) --- **Отказ от отговорност**: -Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматичните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия изходен език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален превод от човек. Ние не носим отговорност за каквито и да е недоразумения или погрешни интерпретации, произтичащи от използването на този превод. \ No newline at end of file +Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод. \ No newline at end of file diff --git a/translations/bn/7-bank-project/4-state-management/README.md b/translations/bn/7-bank-project/4-state-management/README.md index dbfdb6d3b..941a50b05 100644 --- a/translations/bn/7-bank-project/4-state-management/README.md +++ b/translations/bn/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# ব্যাংকিং অ্যাপ তৈরি করুন পার্ট ৪: স্টেট ম্যানেজমেন্টের ধারণা +# একটি ব্যাংকিং অ্যাপ তৈরি করুন পর্ব ৪: স্টেট ম্যানেজমেন্টের ধারণা ## প্রাক-লেকচার কুইজ @@ -15,15 +15,15 @@ CO_OP_TRANSLATOR_METADATA: ### ভূমিকা -যখন একটি ওয়েব অ্যাপ্লিকেশন বড় হয়, তখন সমস্ত ডেটা প্রবাহ ট্র্যাক করা একটি চ্যালেঞ্জ হয়ে দাঁড়ায়। কোন কোড ডেটা পায়, কোন পৃষ্ঠা এটি ব্যবহার করে, কোথায় এবং কখন এটি আপডেট করতে হবে...এটি সহজেই জটিল কোডে পরিণত হতে পারে যা রক্ষণাবেক্ষণ করা কঠিন। এটি বিশেষভাবে সত্য যখন আপনার অ্যাপের বিভিন্ন পৃষ্ঠার মধ্যে ডেটা শেয়ার করতে হয়, যেমন ব্যবহারকারীর তথ্য। *স্টেট ম্যানেজমেন্ট* ধারণাটি সব ধরনের প্রোগ্রামে সবসময়ই বিদ্যমান ছিল, কিন্তু ওয়েব অ্যাপগুলো ক্রমাগত জটিল হয়ে উঠার সাথে সাথে এটি এখন উন্নয়নের সময় একটি গুরুত্বপূর্ণ বিষয় হয়ে উঠেছে। +যখন একটি ওয়েব অ্যাপ্লিকেশন বড় হয়, তখন সমস্ত ডেটা প্রবাহ ট্র্যাক রাখা একটি চ্যালেঞ্জ হয়ে দাঁড়ায়। কোন কোড ডেটা পায়, কোন পৃষ্ঠা এটি ব্যবহার করে, কোথায় এবং কখন এটি আপডেট করতে হবে... সহজেই এমন কোড তৈরি হতে পারে যা বজায় রাখা কঠিন। এটি বিশেষত সত্য যখন আপনার অ্যাপের বিভিন্ন পৃষ্ঠার মধ্যে ডেটা শেয়ার করতে হয়, যেমন ব্যবহারকারীর ডেটা। *স্টেট ম্যানেজমেন্ট* ধারণাটি সব ধরণের প্রোগ্রামে সবসময়ই বিদ্যমান ছিল, তবে ওয়েব অ্যাপ্লিকেশনগুলির জটিলতা বাড়ার সাথে সাথে এটি এখন উন্নয়নের সময় একটি গুরুত্বপূর্ণ বিষয় হয়ে উঠেছে। -এই চূড়ান্ত অংশে, আমরা আমাদের তৈরি করা অ্যাপটি পুনর্বিবেচনা করব কিভাবে স্টেট পরিচালিত হয়, ব্রাউজার রিফ্রেশের জন্য যেকোনো সময় সমর্থন প্রদান করে এবং ব্যবহারকারীর সেশনের মধ্যে ডেটা সংরক্ষণ করে। +এই চূড়ান্ত অংশে, আমরা আমাদের তৈরি করা অ্যাপটি পুনর্বিবেচনা করব কিভাবে স্টেট পরিচালিত হয়, ব্রাউজার রিফ্রেশের জন্য যে কোনো সময় সমর্থন প্রদান করে এবং ব্যবহারকারীর সেশনের মধ্যে ডেটা সংরক্ষণ করে। ### পূর্বশর্ত -এই পাঠের জন্য আপনাকে ওয়েব অ্যাপের [ডেটা ফেচিং](../3-data/README.md) অংশ সম্পন্ন করতে হবে। আপনাকে [Node.js](https://nodejs.org) ইনস্টল করতে হবে এবং [সার্ভার API চালাতে হবে](../api/README.md) লোকালভাবে যাতে আপনি অ্যাকাউন্ট ডেটা পরিচালনা করতে পারেন। +এই পাঠের জন্য আপনাকে [ডেটা ফেচিং](../3-data/README.md) অংশটি সম্পন্ন করতে হবে। আপনাকে [Node.js](https://nodejs.org) ইনস্টল করতে হবে এবং [সার্ভার API চালাতে হবে](../api/README.md) যাতে আপনি অ্যাকাউন্ট ডেটা পরিচালনা করতে পারেন। -আপনি টার্মিনালে এই কমান্ডটি চালিয়ে নিশ্চিত করতে পারেন যে সার্ভার সঠিকভাবে চলছে: +আপনি টার্মিনালে এই কমান্ডটি চালিয়ে পরীক্ষা করতে পারেন যে সার্ভারটি সঠিকভাবে চলছে কিনা: ```sh curl http://localhost:5000/api @@ -32,32 +32,32 @@ curl http://localhost:5000/api --- -## স্টেট ম্যানেজমেন্ট পুনর্বিবেচনা করুন +## স্টেট ম্যানেজমেন্ট পুনর্বিবেচনা -[পূর্ববর্তী পাঠে](../3-data/README.md), আমরা আমাদের অ্যাপে একটি মৌলিক স্টেট ধারণা প্রবর্তন করেছি `account` গ্লোবাল ভেরিয়েবল দিয়ে, যা বর্তমানে লগ ইন করা ব্যবহারকারীর ব্যাংক ডেটা ধারণ করে। তবে, আমাদের বর্তমান বাস্তবায়নে কিছু ত্রুটি রয়েছে। ড্যাশবোর্ডে থাকাকালীন পৃষ্ঠা রিফ্রেশ করার চেষ্টা করুন। কী ঘটে? +[পূর্ববর্তী পাঠে](../3-data/README.md), আমরা আমাদের অ্যাপে একটি মৌলিক স্টেট ধারণা প্রবর্তন করেছি `account` গ্লোবাল ভেরিয়েবলের মাধ্যমে, যা বর্তমানে লগ ইন করা ব্যবহারকারীর ব্যাংক ডেটা ধারণ করে। তবে, আমাদের বর্তমান বাস্তবায়নে কিছু ত্রুটি রয়েছে। ড্যাশবোর্ডে থাকাকালীন পৃষ্ঠাটি রিফ্রেশ করার চেষ্টা করুন। কী ঘটে? -বর্তমান কোডে তিনটি সমস্যা রয়েছে: +বর্তমান কোডে ৩টি সমস্যা রয়েছে: -- স্টেট সংরক্ষিত নয়, কারণ ব্রাউজার রিফ্রেশ আপনাকে লগইন পৃষ্ঠায় ফিরিয়ে নিয়ে যায়। -- স্টেট পরিবর্তন করার জন্য একাধিক ফাংশন রয়েছে। অ্যাপটি বড় হলে এটি পরিবর্তনগুলো ট্র্যাক করা কঠিন করে তুলতে পারে এবং একটি আপডেট করতে ভুল হওয়া সহজ। -- স্টেট পরিষ্কার করা হয় না, তাই যখন আপনি *লগআউট* ক্লিক করেন তখন অ্যাকাউন্ট ডেটা এখনও থাকে যদিও আপনি লগইন পৃষ্ঠায় রয়েছেন। +- স্টেট সংরক্ষিত হয় না, কারণ ব্রাউজার রিফ্রেশ আপনাকে লগইন পৃষ্ঠায় ফিরিয়ে নিয়ে যায়। +- স্টেট পরিবর্তন করে এমন একাধিক ফাংশন রয়েছে। অ্যাপটি বড় হলে এটি পরিবর্তনগুলি ট্র্যাক করা কঠিন করে তোলে এবং একটি আপডেট ভুলে যাওয়া সহজ। +- স্টেট পরিষ্কার করা হয় না, তাই যখন আপনি *লগআউট* এ ক্লিক করেন, তখনও অ্যাকাউন্ট ডেটা থেকে যায় যদিও আপনি লগইন পৃষ্ঠায় আছেন। -আমরা এই সমস্যাগুলো একে একে সমাধান করতে আমাদের কোড আপডেট করতে পারি, তবে এটি আরও কোড ডুপ্লিকেশন তৈরি করবে এবং অ্যাপটিকে আরও জটিল এবং রক্ষণাবেক্ষণ করা কঠিন করে তুলবে। অথবা আমরা কয়েক মিনিটের জন্য বিরতি নিতে পারি এবং আমাদের কৌশল পুনর্বিবেচনা করতে পারি। +আমরা এই সমস্যাগুলি একে একে সমাধান করতে আমাদের কোড আপডেট করতে পারি, তবে এটি আরও কোড ডুপ্লিকেশন তৈরি করবে এবং অ্যাপটিকে আরও জটিল এবং বজায় রাখা কঠিন করে তুলবে। অথবা আমরা কয়েক মিনিটের জন্য বিরতি নিয়ে আমাদের কৌশল পুনর্বিবেচনা করতে পারি। -> আমরা এখানে আসলে কোন সমস্যাগুলো সমাধান করার চেষ্টা করছি? +> এখানে আমরা আসলে কোন সমস্যাগুলি সমাধান করার চেষ্টা করছি? -[স্টেট ম্যানেজমেন্ট](https://en.wikipedia.org/wiki/State_management) হলো এই দুটি নির্দিষ্ট সমস্যার জন্য একটি ভালো পদ্ধতি খুঁজে বের করার বিষয়ে: +[স্টেট ম্যানেজমেন্ট](https://en.wikipedia.org/wiki/State_management) হল এই দুটি নির্দিষ্ট সমস্যার জন্য একটি ভাল পদ্ধতি খুঁজে বের করা: -- কীভাবে একটি অ্যাপে ডেটা প্রবাহগুলোকে বোধগম্য রাখা যায়? -- কীভাবে স্টেট ডেটাকে সবসময় ব্যবহারকারীর ইন্টারফেসের সাথে সিঙ্কে রাখা যায় (এবং এর বিপরীত)? +- কীভাবে একটি অ্যাপে ডেটা প্রবাহগুলো বোধগম্য রাখা যায়? +- কীভাবে স্টেট ডেটা সর্বদা ব্যবহারকারীর ইন্টারফেসের সাথে সিঙ্কে রাখা যায় (এবং এর বিপরীত)? -আপনি যখন এগুলো যত্ন সহকারে পরিচালনা করবেন, তখন আপনার যে কোনো অন্যান্য সমস্যা হয়তো ইতিমধ্যেই সমাধান হয়ে যাবে বা সমাধান করা সহজ হয়ে যাবে। এই সমস্যাগুলো সমাধানের জন্য অনেক সম্ভাব্য পদ্ধতি রয়েছে, তবে আমরা একটি সাধারণ সমাধান গ্রহণ করব যা **ডেটা এবং এটি পরিবর্তনের উপায়গুলো কেন্দ্রীভূত করার** ধারণা নিয়ে কাজ করে। ডেটা প্রবাহগুলো এইভাবে চলবে: +আপনি যখন এগুলির যত্ন নেবেন, তখন আপনার যে কোনো অন্যান্য সমস্যা হয়তো ইতিমধ্যেই সমাধান হয়ে যাবে বা সমাধান করা সহজ হয়ে যাবে। এই সমস্যাগুলি সমাধানের জন্য অনেক সম্ভাব্য পদ্ধতি রয়েছে, তবে আমরা একটি সাধারণ সমাধান বেছে নেব যা **ডেটা এবং এটি পরিবর্তনের উপায়গুলিকে কেন্দ্রীভূত করার** ধারণার উপর ভিত্তি করে। ডেটা প্রবাহগুলো নিম্নরূপ হবে: -![HTML, ব্যবহারকারীর ক্রিয়া এবং স্টেটের মধ্যে ডেটা প্রবাহের স্কিমা](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.bn.png) +![HTML, ব্যবহারকারীর ক্রিয়া এবং স্টেটের মধ্যে ডেটা প্রবাহ দেখানো একটি স্কিমা](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.bn.png) -> আমরা এখানে সেই অংশটি কভার করব না যেখানে ডেটা স্বয়ংক্রিয়ভাবে ভিউ আপডেটকে ট্রিগার করে, কারণ এটি [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming)-এর আরও উন্নত ধারণার সাথে সম্পর্কিত। এটি একটি গভীর ডাইভের জন্য একটি ভালো অনুসরণ বিষয়। +> এখানে আমরা সেই অংশটি কভার করব না যেখানে ডেটা স্বয়ংক্রিয়ভাবে ভিউ আপডেটকে ট্রিগার করে, কারণ এটি [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming)-এর আরও উন্নত ধারণার সাথে সম্পর্কিত। এটি একটি গভীর ডাইভের জন্য একটি ভাল অনুসরণ বিষয়। -✅ স্টেট ম্যানেজমেন্টের জন্য অনেক লাইব্রেরি রয়েছে, [Redux](https://redux.js.org) একটি জনপ্রিয় অপশন। এর ধারণা এবং প্যাটার্নগুলো দেখুন কারণ এটি প্রায়ই বড় ওয়েব অ্যাপগুলোতে সম্ভাব্য সমস্যাগুলো এবং কীভাবে সেগুলো সমাধান করা যায় তা শেখার একটি ভালো উপায়। +✅ স্টেট ম্যানেজমেন্টের জন্য বিভিন্ন পদ্ধতির সাথে অনেক লাইব্রেরি রয়েছে, [Redux](https://redux.js.org) একটি জনপ্রিয় বিকল্প। এর ধারণা এবং প্যাটার্নগুলি দেখুন কারণ এটি প্রায়শই শেখার একটি ভাল উপায় যে বড় ওয়েব অ্যাপগুলিতে আপনি কী সম্ভাব্য সমস্যার সম্মুখীন হতে পারেন এবং কীভাবে এটি সমাধান করা যায়। ### কাজ @@ -75,9 +75,9 @@ let state = { }; ``` -ধারণাটি হলো আমাদের অ্যাপের সমস্ত ডেটাকে একটি একক স্টেট অবজেক্টে *কেন্দ্রীভূত* করা। আমাদের স্টেটে এখন শুধুমাত্র `account` রয়েছে, তাই এটি খুব বেশি পরিবর্তন করে না, তবে এটি ভবিষ্যতের জন্য একটি পথ তৈরি করে। +ধারণাটি হল আমাদের অ্যাপের সমস্ত ডেটা একটি একক স্টেট অবজেক্টে *কেন্দ্রীভূত* করা। আপাতত আমাদের স্টেটে শুধুমাত্র `account` রয়েছে, তাই এটি খুব বেশি পরিবর্তন করে না, তবে এটি ভবিষ্যতের জন্য একটি পথ তৈরি করে। -আমাদের এটি ব্যবহারকারী ফাংশনগুলোও আপডেট করতে হবে। `register()` এবং `login()` ফাংশনে, `account = ...` প্রতিস্থাপন করুন `state.account = ...`; +আমাদের এটি ব্যবহারকারী ফাংশনগুলিও আপডেট করতে হবে। `register()` এবং `login()` ফাংশনে, `account = ...` প্রতিস্থাপন করুন `state.account = ...`; `updateDashboard()` ফাংশনের শুরুতে এই লাইনটি যোগ করুন: @@ -89,13 +89,13 @@ const account = state.account; ## ডেটা পরিবর্তন ট্র্যাক করুন -এখন আমরা আমাদের ডেটা সংরক্ষণ করার জন্য `state` অবজেক্টটি স্থাপন করেছি, পরবর্তী ধাপ হলো আপডেটগুলো কেন্দ্রীভূত করা। লক্ষ্য হলো যে কোনো পরিবর্তন এবং কখন তা ঘটে তা ট্র্যাক করা সহজ করা। +এখন যেহেতু আমরা আমাদের ডেটা সংরক্ষণ করতে `state` অবজেক্টটি স্থাপন করেছি, পরবর্তী ধাপ হল আপডেটগুলো কেন্দ্রীভূত করা। লক্ষ্য হল যে কোনো পরিবর্তন এবং কখন সেগুলি ঘটে তা ট্র্যাক করা সহজ করা। -`state` অবজেক্টে পরিবর্তনগুলো এড়াতে, এটিকে [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) বিবেচনা করাও একটি ভালো অভ্যাস, যার অর্থ এটি মোটেও পরিবর্তন করা যাবে না। এর অর্থ হলো আপনি যদি এতে কিছু পরিবর্তন করতে চান তবে আপনাকে একটি নতুন স্টেট অবজেক্ট তৈরি করতে হবে। এটি করে আপনি সম্ভাব্য অনাকাঙ্ক্ষিত [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) সম্পর্কে সুরক্ষা তৈরি করেন এবং আপনার অ্যাপে নতুন বৈশিষ্ট্য বাস্তবায়নের জন্য সম্ভাবনা খুলে দেন যেমন undo/redo বাস্তবায়ন করা, পাশাপাশি এটি ডিবাগ করা সহজ করে তোলে। উদাহরণস্বরূপ, আপনি স্টেটে করা প্রতিটি পরিবর্তন লগ করতে পারেন এবং একটি বাগের উৎস বুঝতে পরিবর্তনের ইতিহাস রাখতে পারেন। +`state` অবজেক্টে পরিবর্তনগুলি এড়াতে, এটিকে [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) বিবেচনা করাও একটি ভাল অভ্যাস, যার অর্থ এটি মোটেও পরিবর্তন করা যাবে না। এর অর্থ হল আপনি যদি এতে কিছু পরিবর্তন করতে চান তবে আপনাকে একটি নতুন স্টেট অবজেক্ট তৈরি করতে হবে। এটি করে, আপনি সম্ভাব্য অবাঞ্ছিত [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) সম্পর্কে সুরক্ষা তৈরি করেন এবং আপনার অ্যাপে নতুন বৈশিষ্ট্য বাস্তবায়নের সম্ভাবনা খুলে দেন যেমন undo/redo বাস্তবায়ন করা, পাশাপাশি এটি ডিবাগ করাও সহজ করে তোলে। উদাহরণস্বরূপ, আপনি স্টেটে করা প্রতিটি পরিবর্তন লগ করতে এবং একটি বাগের উত্স বুঝতে পরিবর্তনের একটি ইতিহাস রাখতে পারেন। -জাভাস্ক্রিপ্টে, আপনি [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) ব্যবহার করতে পারেন একটি অবজেক্টের অপরিবর্তনীয় সংস্করণ তৈরি করতে। আপনি যদি একটি অপরিবর্তনীয় অবজেক্টে পরিবর্তন করার চেষ্টা করেন, তবে একটি ব্যতিক্রম উত্থাপিত হবে। +জাভাস্ক্রিপ্টে, আপনি [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) ব্যবহার করে একটি অবিচলিত সংস্করণ তৈরি করতে পারেন। যদি আপনি একটি অবিচলিত অবজেক্টে পরিবর্তন করার চেষ্টা করেন, তবে একটি ব্যতিক্রম উত্থাপিত হবে। -✅ আপনি কি জানেন একটি *shallow* এবং একটি *deep* অপরিবর্তনীয় অবজেক্টের মধ্যে পার্থক্য কী? আপনি এটি সম্পর্কে [এখানে](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) পড়তে পারেন। +✅ আপনি কি জানেন একটি *shallow* এবং একটি *deep* অবিচলিত অবজেক্টের মধ্যে পার্থক্য কী? আপনি এটি সম্পর্কে পড়তে পারেন [এখানে](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze)। ### কাজ @@ -110,9 +110,9 @@ function updateState(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` প্রপার্টি সংরক্ষিত আছে, তবে এই পদ্ধতির মাধ্যমে আপনি স্টেটে যত প্রপার্টি প্রয়োজন যোগ করতে পারেন। +এই ফাংশনে, আমরা একটি নতুন স্টেট অবজেক্ট তৈরি করছি এবং পূর্ববর্তী স্টেট থেকে ডেটা কপি করছি [*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` ইনিশিয়ালাইজেশনও আপডেট করব যাতে প্রাথমিক স্টেটও ফ্রিজ করা হয়: +আমরা নিশ্চিত করব যে প্রাথমিক স্টেটও ফ্রোজেন, এজন্য `state` ইনিশিয়ালাইজেশন আপডেট করব: ```js let state = Object.freeze({ @@ -120,19 +120,19 @@ let state = Object.freeze({ }); ``` -এর পরে, `register` ফাংশন আপডেট করুন `state.account = result;` অ্যাসাইনমেন্ট প্রতিস্থাপন করে: +এরপর, `register` ফাংশন আপডেট করুন এবং `state.account = result;` অ্যাসাইনমেন্টটি প্রতিস্থাপন করুন: ```js updateState('account', result); ``` -`login` ফাংশনের ক্ষেত্রেও একই কাজ করুন, `state.account = data;` প্রতিস্থাপন করে: +`login` ফাংশনের ক্ষেত্রেও একই কাজ করুন, `state.account = data;` প্রতিস্থাপন করুন: ```js updateState('account', data); ``` -আমরা এখন *লগআউট* ক্লিক করার সময় অ্যাকাউন্ট ডেটা পরিষ্কার না হওয়ার সমস্যাটি সমাধান করার সুযোগ নেব। +এখন আমরা *লগআউট* বাটনে ক্লিক করার সময় অ্যাকাউন্ট ডেটা পরিষ্কার না হওয়ার সমস্যাটি সমাধান করব। একটি নতুন `logout()` ফাংশন তৈরি করুন: @@ -143,35 +143,35 @@ function logout() { } ``` -`updateDashboard()`-এ, `return navigate('/login');` রিডিরেকশনটি প্রতিস্থাপন করুন `return logout();` দিয়ে; +`updateDashboard()`-এ, `return navigate('/login');` রিডিরেকশনটি প্রতিস্থাপন করুন `return logout();` দিয়ে। -একটি নতুন অ্যাকাউন্ট রেজিস্টার করার চেষ্টা করুন, লগআউট করুন এবং আবার লগইন করুন যাতে সবকিছু এখনও সঠিকভাবে কাজ করছে কিনা তা পরীক্ষা করা যায়। +একটি নতুন অ্যাকাউন্ট রেজিস্টার করুন, লগআউট করুন এবং আবার লগইন করুন এটি সঠিকভাবে কাজ করছে কিনা তা পরীক্ষা করতে। -> টিপ: আপনি ব্রাউজারের ডেভেলপমেন্ট টুলসের কনসোলে `updateState()`-এর নিচে `console.log(state)` যোগ করে সমস্ত স্টেট পরিবর্তন দেখতে পারেন। +> টিপ: আপনি ব্রাউজারের ডেভেলপমেন্ট টুলসের কনসোলে `updateState()`-এর শেষে `console.log(state)` যোগ করে সমস্ত স্টেট পরিবর্তন দেখতে পারেন। ## স্টেট সংরক্ষণ করুন -বেশিরভাগ ওয়েব অ্যাপ সঠিকভাবে কাজ করতে ডেটা সংরক্ষণ করতে হয়। সমস্ত গুরুত্বপূর্ণ ডেটা সাধারণত একটি ডাটাবেসে সংরক্ষণ করা হয় এবং একটি সার্ভার API এর মাধ্যমে অ্যাক্সেস করা হয়, যেমন আমাদের ক্ষেত্রে ব্যবহারকারীর অ্যাকাউন্ট ডেটা। তবে কখনও কখনও, ব্রাউজারে চলমান ক্লায়েন্ট অ্যাপে কিছু ডেটা সংরক্ষণ করাও আকর্ষণীয় হতে পারে, একটি ভালো ব্যবহারকারীর অভিজ্ঞতা বা লোডিং পারফরম্যান্স উন্নত করার জন্য। +অধিকাংশ ওয়েব অ্যাপ্লিকেশনের সঠিকভাবে কাজ করার জন্য ডেটা সংরক্ষণ করতে হয়। সমস্ত গুরুত্বপূর্ণ ডেটা সাধারণত একটি ডাটাবেসে সংরক্ষণ করা হয় এবং একটি সার্ভার API এর মাধ্যমে অ্যাক্সেস করা হয়, যেমন আমাদের ক্ষেত্রে ব্যবহারকারীর অ্যাকাউন্ট ডেটা। তবে কখনও কখনও, ব্রাউজারে চলমান ক্লায়েন্ট অ্যাপে কিছু ডেটা সংরক্ষণ করাও আকর্ষণীয়, একটি ভাল ব্যবহারকারীর অভিজ্ঞতার জন্য বা লোডিং পারফরম্যান্স উন্নত করার জন্য। -যখন আপনি আপনার ব্রাউজারে ডেটা সংরক্ষণ করতে চান, তখন কয়েকটি গুরুত্বপূর্ণ প্রশ্ন জিজ্ঞাসা করা উচিত: +যখন আপনি আপনার ব্রাউজারে ডেটা সংরক্ষণ করতে চান, তখন আপনাকে কয়েকটি গুরুত্বপূর্ণ প্রশ্ন জিজ্ঞাসা করা উচিত: - *ডেটা কি সংবেদনশীল?* আপনি ক্লায়েন্টে কোনো সংবেদনশীল ডেটা সংরক্ষণ এড়িয়ে চলা উচিত, যেমন ব্যবহারকারীর পাসওয়ার্ড। -- *আপনার এই ডেটা কতক্ষণ ধরে রাখতে হবে?* আপনি কি এই ডেটা শুধুমাত্র বর্তমান সেশনের জন্য অ্যাক্সেস করতে চান নাকি এটি চিরতরে সংরক্ষণ করতে চান? +- *আপনাকে কতক্ষণ এই ডেটা রাখতে হবে?* আপনি কি শুধুমাত্র বর্তমান সেশনের জন্য এই ডেটা অ্যাক্সেস করার পরিকল্পনা করছেন নাকি এটি চিরতরে সংরক্ষণ করতে চান? -ওয়েব অ্যাপের ভিতরে তথ্য সংরক্ষণের জন্য বিভিন্ন উপায় রয়েছে, আপনি যা অর্জন করতে চান তার উপর নির্ভর করে। উদাহরণস্বরূপ, আপনি একটি সার্চ কোয়েরি সংরক্ষণ করতে URL ব্যবহার করতে পারেন এবং এটি ব্যবহারকারীদের মধ্যে শেয়ারযোগ্য করতে পারেন। আপনি [HTTP কুকিজ](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ব্যবহার করতে পারেন যদি ডেটা সার্ভারের সাথে শেয়ার করতে হয়, যেমন [authentication](https://en.wikipedia.org/wiki/Authentication) তথ্য। +ওয়েব অ্যাপ্লিকেশনের ভিতরে তথ্য সংরক্ষণের জন্য বিভিন্ন উপায় রয়েছে, আপনি যা অর্জন করতে চান তার উপর নির্ভর করে। উদাহরণস্বরূপ, আপনি একটি সার্চ কোয়েরি সংরক্ষণ করতে URL ব্যবহার করতে পারেন এবং এটি ব্যবহারকারীদের মধ্যে শেয়ারযোগ্য করতে পারেন। আপনি [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ব্যবহার করতে পারেন যদি ডেটা সার্ভারের সাথে শেয়ার করতে হয়, যেমন [authentication](https://en.wikipedia.org/wiki/Authentication) তথ্য। -আরেকটি অপশন হলো ডেটা সংরক্ষণের জন্য ব্রাউজারের অনেক API এর মধ্যে একটি ব্যবহার করা। দুটি বিশেষভাবে আকর্ষণীয়: +আরেকটি বিকল্প হল ডেটা সংরক্ষণের জন্য ব্রাউজারের অনেক 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` এর মতো কাজ করে তবে এতে সংরক্ষিত ডেটা সেশন শেষ হলে (যখন ব্রাউজার বন্ধ হয়) মুছে ফেলা হয়। +- [`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](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) ফরম্যাটে সিরিয়ালাইজ করতে হবে [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) ব্যবহার করে। -✅ আপনি যদি একটি ওয়েব অ্যাপ তৈরি করতে চান যা সার্ভার ছাড়াই কাজ করে, তবে এটি [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) ব্যবহার করে ক্লায়েন্টে একটি ডাটাবেস তৈরি করাও সম্ভব। এটি উন্নত ব্যবহারের ক্ষেত্রে বা যদি আপনি উল্লেখযোগ্য পরিমাণ ডেটা সংরক্ষণ করতে চান তবে সংরক্ষিত, কারণ এটি ব্যবহার করা আরও জটিল। +✅ আপনি যদি এমন একটি ওয়েব অ্যাপ তৈরি করতে চান যা সার্ভার ছাড়াই কাজ করে, তবে [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) ব্যবহার করে ক্লায়েন্টে একটি ডাটাবেস তৈরি করাও সম্ভব। এটি উন্নত ব্যবহারের ক্ষেত্রে বা যদি আপনাকে উল্লেখযোগ্য পরিমাণ ডেটা সংরক্ষণ করতে হয় তবে এটি আরও জটিল ব্যবহারের জন্য সংরক্ষিত। ### কাজ -আমরা চাই আমাদের ব্যবহারকারীরা *লগআউট* বোতামে স্পষ্টভাবে ক্লিক না করা পর্যন্ত লগ ইন অবস্থায় থাকুক, তাই আমরা `localStorage` ব্যবহার করব অ্যাকাউন্ট ডেটা সংরক্ষণ করতে। প্রথমে, আসুন একটি কী সংজ্ঞায়িত করি যা আমরা আমাদের ডেটা সংরক্ষণের জন্য ব্যবহার করব। +আমরা চাই আমাদের ব্যবহারকারীরা *লগআউট* বাটনে স্পষ্টভাবে ক্লিক না করা পর্যন্ত লগ ইন থাকুক, তাই আমরা `localStorage` ব্যবহার করে অ্যাকাউন্ট ডেটা সংরক্ষণ করব। প্রথমে, আমরা একটি কী সংজ্ঞায়িত করব যা আমরা আমাদের ডেটা সংরক্ষণ করতে ব্যবহার করব। ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -এর মাধ্যমে, ব্যবহারকারীর অ্যাকাউন্ট ডেটা সংরক্ষিত থাকবে এবং আমরা পূর্বে কেন্দ্রীভূত সমস্ত স্টেট আপডেটের জন্য সর্বদা আপ-টু-ডেট থাকবে। এটি হলো যেখানে আমরা আমাদের পূর্ববর্তী রিফ্যাক্টরগুলো থেকে উপকৃত হতে শুরু করি 🙂। +এটির মাধ্যমে, ব্যবহারকারীর অ্যাকাউন্ট ডেটা সংরক্ষিত থাকবে এবং পূর্বে কেন্দ্রীভূত করা সমস্ত স্টেট আপডেটের মতো সর্বদা আপডেট থাকবে। এটি সেই জায়গা যেখানে আমরা আমাদের পূর্ববর্তী রিফ্যাক্টরগুলির সমস্ত সুবিধা পেতে শুরু করি 🙂। -ডেটা সংরক্ষিত হওয়ার কারণে, আমাদের অ্যাপ লোড হওয়ার সময় এটি পুনরুদ্ধার করার যত্নও নিতে হবে। যেহেতু আমরা আরও ইনিশিয়ালাইজেশন কোড পেতে শুরু করব, এটি একটি নতুন `init` ফাংশন তৈরি করার জন্য একটি ভালো ধারণা হতে পারে, যা `app.js`-এর নিচে আমাদের পূর্ববর্তী কোডও অন্তর্ভুক্ত করে: +ডেটা সংরক্ষণ করা হয়েছে, তাই আমাদের অ্যাপটি লোড হওয়ার সময় এটি পুনরুদ্ধার করার যত্নও নিতে হবে। যেহেতু আমরা আরও ইনিশিয়ালাইজেশন কোড পেতে শুরু করব, এটি একটি নতুন `init` ফাংশন তৈরি করার একটি ভাল ধারণা হতে পারে, যা `app.js`-এর নীচের পূর্ববর্তী কোডটিও অন্তর্ভুক্ত করে: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -এখানে আমরা সংরক্ষিত ডেটা পুনরুদ্ধার করি, এবং যদি কোনো ডেটা থাকে তবে আমরা স্টেট অনুযায়ী আপডেট করি। এটি *রুট* আপডেট করার *আগে* করা গুরুত্বপূর্ণ, কারণ পৃষ্ঠা আপডেটের সময় স্টেটের উপর নির্ভরশীল কোড থাকতে পারে। +এখানে আমরা সংরক্ষিত ডেটা পুনরুদ্ধার করি, এবং যদি কোনো ডেটা থাকে তবে আমরা স্টেটটি অনুযায়ী আপডেট করি। এটি রুট আপডেট করার *আগে* করা গুরুত্বপূর্ণ, কারণ পৃষ্ঠা আপডেটের সময় স্টেটের উপর নির্ভরশীল কোড থাকতে পারে। -আমরা *ড্যাশবোর্ড* পৃষ্ঠাকে আমাদের অ্যাপ্লিকেশনের ডিফল্ট পৃষ্ঠা করতে পারি, কারণ আমরা এখন অ্যাকাউন্ট ডেটা সংরক্ষণ করছি। যদি কোনো ডেটা পাওয়া না যায়, ড্যাশবোর্ড যেকোনোভাবে *লগইন* পৃষ্ঠায় রিডিরেক্ট করার যত্ন নেয়। `updateRoute()`-এ, `return navigate('/login');` ফallback প্রতিস্থাপন করুন `return navigate('/dashboard');` দিয়ে। +আমরা *ড্যাশবোর্ড* পৃষ্ঠাটিকে আমাদের অ্যাপ্লিকেশনের ডিফল্ট পৃষ্ঠা বানাতে পারি, কারণ আমরা এখন অ্যাকাউন্ট ডেটা সংরক্ষণ করছি। যদি কোনো ডেটা পাওয়া না যায়, তবে ড্যাশবোর্ডটি যেকোনোভাবে *লগইন* পৃষ্ঠায় রিডিরেক্ট করার যত্ন নেয়। `updateRoute()`-এ, ফallback `return navigate('/login');` প্রতিস্থাপন করুন `return navigate('/dashboard');` দিয়ে। -এখন অ্যাপে লগইন করুন এবং পৃষ্ঠা রিফ্রেশ করার চেষ্টা করুন। আপনি ড্যাশবোর্ডে থাকা উচিত। এই আপডেটের মাধ্যমে আমরা আমাদের সমস্ত প্রাথমিক সমস্যার যত্ন নিয়েছি... +এখন অ্যাপে লগইন করুন এবং পৃষ্ঠাটি রিফ্রেশ করার চেষ্টা করুন। আপনি ড্যাশবোর্ডে থাকা উচিত। এই আপডেটের মাধ্যমে আমরা আমাদের সমস্ত প্রাথমিক সমস্যার যত্ন নিয়েছি... ## ডেটা রিফ্রেশ করুন ...কিন্তু আমরা হয়তো একটি নতুন সমস্যা তৈরি করেছি। ওহ! -`test` অ্যাকাউন্ট ব্যবহার করে ড্যাশবোর্ডে যান, তারপর একটি নতুন লেনদেন তৈরি করতে টার্মিনালে এই কমান্ডটি চালান: +`test` অ্যাকাউন্ট ব্যবহার করে ড্যাশবোর্ডে যান, তারপর একটি নতুন লেনদেন তৈরি করতে একটি টার্মিনালে এই কমান্ডটি চালান: ```sh curl --request POST \ @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -এখন ব্রাউজারে ড্যাশবোর্ড পৃষ্ঠা রিফ্রেশ করার চেষ্টা করুন। কী ঘটে? আপনি কি নতুন লেনদেনটি দেখতে পাচ্ছেন? +এখন আপনার ব্রাউজারে ড্যাশবোর্ড পৃষ্ঠাটি রিফ্রেশ করার চেষ্টা করুন। কী ঘটে? আপনি কি নতুন লেনদেনটি দেখতে পাচ্ছেন? -স্টেটটি `localStorage` এর মাধ্যমে অনির্দিষ্টকালের জন্য সংরক্ষিত থাকে, তবে এর অর্থ হলো এটি কখনোই আপডেট হয় না যতক্ষণ না আপনি অ্যাপ থেকে লগ আউট করেন এবং আবার লগ ইন করেন! +`localStorage`-এর জন্য ধন্যবাদ, স্টেট অনির্দিষ্টকালের জন্য সংরক্ষিত থাকে, তবে এর অর্থ হল এটি কখনও আপডেট হয় না যতক্ষণ না আপনি অ্যাপ থেকে লগ আউট করেন এবং আবার লগ ইন করেন! -এটি ঠিক করার একটি সম্ভাব্য কৌশল হলো ড্যাশবোর্ড লোড হওয়ার প্রতিবার অ্যাকাউন্ট ডেটা পুনরায় লোড করা, স্থবির ডেটা এড়ানোর জন্য। +এটি ঠিক করার একটি সম্ভাব্য কৌশল হল ড্যাশবোর্ড লোড হওয়ার প্রতিবার অ্যাকাউন্ট ডেটা পুনরায় লোড করা, স্থবির ডেটা এড়াতে। ### কাজ @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -এই মেথডটি পরীক্ষা করে যে আমরা বর্তমানে লগ ইন অবস্থায় আছি, তারপর সার্ভার থেকে অ্যাকাউন্ট ডেটা পুনরায় লোড করে। +এই পদ্ধতিটি পরীক্ষা করে যে আমরা বর্তমানে লগ ইন আছি কিনা তারপর সার্ভার থেকে অ্যাকাউন্ট ডেটা পুনরায় লোড করে। `refresh` নামে আরেকটি ফাংশন তৈরি করুন: @@ -258,7 +258,7 @@ async function refresh() { } ``` -এটি অ্যাকাউন্ট ডেটা আপডেট করে, তারপর ড্যাশবোর্ড পৃষ্ঠার HTML আপডেট করার যত্ন নেয়। এটি হলো যা আমরা ড্যাশবোর্ড রুট লোড হওয়ার সময় কল করতে চাই। রুট সংজ্ঞা আপডেট করুন: +এটি অ্যাকাউন্ট ডেটা আপডেট করে, তারপর ড্যাশবোর্ড পৃষ্ঠার HTML আপডেট করার যত্ন নেয়। এটি আমরা ড্যাশবোর্ড রুট লোড হওয়ার সময় কল করতে চাই। রুট সংজ্ঞাটি আপডেট করুন: ```js const routes = { @@ -267,26 +267,28 @@ const routes = { }; ``` -এখন ড্যাশবোর্ড রিফ্রেশ করার চেষ্টা করুন, এটি আপডেট করা অ্যাকাউন্ট ডেটা প্রদর্শন করা উচিত। +এখন ড্যাশবোর্ড রিফ্রেশ করার চেষ্টা করুন, এটি আপডেট হওয়া অ্যাকাউন্ট ডেটা প্রদর্শন করা উচিত। --- ## 🚀 চ্যালেঞ্জ -এখন আমরা ড্যাশবোর্ড লোড হওয়ার প্রতিবার অ্যাকাউন্ট ডেটা পুনরায় লোড করি, আপনি কি মনে করেন আমরা এখনও *সমস্ত অ্যাকাউন্ট* ডেটা সংরক্ষণ করতে হবে? +এখন যেহেতু আমরা ড্যাশবোর্ড লোড হওয়ার প্রতিবার অ্যাকাউন্ট ডেটা পুনরায় লোড করি, আপনি কি মনে করেন যে আমরা এখনও *সমস্ত অ্যাকাউন্ট* ডেটা সংরক্ষণ করতে হবে? -একসাথে কাজ করার চেষ্টা করুন `localStorage` থেকে কী সংরক্ষণ এবং লোড করা হয় তা পরিবর্তন করতে যাতে অ্যাপটি কাজ করার জন্য শুধুমাত্র যা একেবারে প্রয়োজন তা অন্তর্ভুক্ত করা হয়। +একসঙ্গে কাজ করে `localStorage` থেকে কী সংরক্ষণ এবং লোড করা হয় তা পরিবর্তন করার চেষ্টা করুন যাতে অ্যাপটি কাজ করার জন্য একেবারে প্রয়োজনীয় জিনিসগুলোই অন্তর্ভুক্ত থাকে। ## পোস্ট-লেকচার কুইজ +[পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/web/quiz/48) -[পোস্ট-লেকচার কুইজ](https://ff-quizzes.netlify.app/web -[লেনদেন যোগ করার ডায়ালগ বাস্তবায়ন করুন](assignment.md) +## অ্যাসাইনমেন্ট -এখানে একটি উদাহরণ ফলাফল রয়েছে যা অ্যাসাইনমেন্ট সম্পন্ন করার পরে দেখা যাবে: +["লেনদেন যোগ করুন" ডায়ালগ বাস্তবায়ন করুন](assignment.md) -![স্ক্রিনশট যেখানে "লেনদেন যোগ করুন" ডায়ালগের একটি উদাহরণ দেখানো হয়েছে](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.bn.png) +অ্যাসাইনমেন্ট সম্পন্ন করার পর একটি উদাহরণ ফলাফল এখানে দেওয়া হলো: + +![স্ক্রিনশট যেখানে একটি উদাহরণ "লেনদেন যোগ করুন" ডায়ালগ দেখানো হয়েছে](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.bn.png) --- **অস্বীকৃতি**: -এই নথিটি AI অনুবাদ পরিষেবা [Co-op Translator](https://github.com/Azure/co-op-translator) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসাধ্য সঠিকতা নিশ্চিত করার চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা দায়বদ্ধ থাকব না। \ No newline at end of file +এই নথিটি AI অনুবাদ পরিষেবা [Co-op Translator](https://github.com/Azure/co-op-translator) ব্যবহার করে অনুবাদ করা হয়েছে। আমরা যথাসাধ্য সঠিকতার জন্য চেষ্টা করি, তবে অনুগ্রহ করে মনে রাখবেন যে স্বয়ংক্রিয় অনুবাদে ত্রুটি বা অসঙ্গতি থাকতে পারে। মূল ভাষায় থাকা নথিটিকে প্রামাণিক উৎস হিসেবে বিবেচনা করা উচিত। গুরুত্বপূর্ণ তথ্যের জন্য, পেশাদার মানব অনুবাদ সুপারিশ করা হয়। এই অনুবাদ ব্যবহারের ফলে কোনো ভুল বোঝাবুঝি বা ভুল ব্যাখ্যা হলে আমরা দায়বদ্ধ থাকব না। \ No newline at end of file diff --git a/translations/br/7-bank-project/4-state-management/README.md b/translations/br/7-bank-project/4-state-management/README.md index 17d215aa4..8b3910525 100644 --- a/translations/br/7-bank-project/4-state-management/README.md +++ b/translations/br/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# Construindo um App Bancário Parte 4: Conceitos de Gerenciamento de Estado +# Construir um App Bancário Parte 4: Conceitos de Gerenciamento de Estado ## Quiz Pré-Aula @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Introdução -À medida que uma aplicação web cresce, torna-se um desafio acompanhar todos os fluxos de dados. Qual código obtém os dados, qual página os consome, onde e quando eles precisam ser atualizados... é fácil acabar com um código bagunçado e difícil de manter. Isso é especialmente verdadeiro quando você precisa compartilhar dados entre diferentes páginas do seu app, como os dados do usuário. O conceito de *gerenciamento de estado* sempre existiu em todos os tipos de programas, mas à medida que os apps web continuam crescendo em complexidade, tornou-se um ponto-chave a ser considerado durante o desenvolvimento. +À medida que uma aplicação web cresce, torna-se um desafio acompanhar todos os fluxos de dados. Qual código obtém os dados, qual página os consome, onde e quando eles precisam ser atualizados... é fácil acabar com um código bagunçado e difícil de manter. Isso é especialmente verdadeiro quando você precisa compartilhar dados entre diferentes páginas do seu app, como os dados do usuário. O conceito de *gerenciamento de estado* sempre existiu em todos os tipos de programas, mas à medida que os aplicativos web continuam crescendo em complexidade, tornou-se um ponto-chave a ser considerado durante o desenvolvimento. Nesta última parte, vamos revisar o app que construímos para repensar como o estado é gerenciado, permitindo suporte para atualização do navegador a qualquer momento e persistindo dados entre sessões do usuário. ### Pré-requisitos -Você precisa ter concluído a parte de [busca de dados](../3-data/README.md) do app web para esta lição. Também é necessário instalar o [Node.js](https://nodejs.org) e [executar a API do servidor](../api/README.md) localmente para gerenciar os dados da conta. +Você precisa ter concluído a parte de [busca de dados](../3-data/README.md) do aplicativo web para esta lição. Também é necessário instalar o [Node.js](https://nodejs.org) e [executar a API do servidor](../api/README.md) localmente para gerenciar os dados da conta. Você pode testar se o servidor está funcionando corretamente executando este comando em um terminal: @@ -32,21 +32,21 @@ curl http://localhost:5000/api --- -## Repensando o gerenciamento de estado +## Repensar o gerenciamento de estado -Na [lição anterior](../3-data/README.md), introduzimos um conceito básico de estado em nosso app com a variável global `account`, que contém os dados bancários do usuário atualmente logado. No entanto, nossa implementação atual tem algumas falhas. Tente atualizar a página enquanto estiver no painel. O que acontece? +Na [lição anterior](../3-data/README.md), introduzimos um conceito básico de estado em nosso app com a variável global `account`, que contém os dados bancários do usuário atualmente logado. No entanto, nossa implementação atual tem algumas falhas. Tente atualizar a página quando estiver no painel. O que acontece? Há 3 problemas com o código atual: - O estado não é persistido, pois uma atualização do navegador leva você de volta à página de login. -- Existem várias funções que modificam o estado. À medida que o app cresce, isso pode dificultar o rastreamento das mudanças e é fácil esquecer de atualizar algo. +- Existem várias funções que modificam o estado. À medida que o app cresce, isso pode dificultar o acompanhamento das mudanças e é fácil esquecer de atualizar algo. - O estado não é limpo, então quando você clica em *Logout*, os dados da conta ainda estão lá, mesmo que você esteja na página de login. Poderíamos atualizar nosso código para resolver esses problemas um por um, mas isso criaria mais duplicação de código e tornaria o app mais complexo e difícil de manter. Ou poderíamos parar por alguns minutos e repensar nossa estratégia. > Quais problemas estamos realmente tentando resolver aqui? -[Gerenciamento de estado](https://en.wikipedia.org/wiki/State_management) trata de encontrar uma boa abordagem para resolver esses dois problemas específicos: +[Gerenciamento de estado](https://en.wikipedia.org/wiki/State_management) trata de encontrar uma abordagem eficaz para resolver esses dois problemas específicos: - Como manter os fluxos de dados em um app compreensíveis? - Como manter os dados de estado sempre sincronizados com a interface do usuário (e vice-versa)? @@ -55,9 +55,9 @@ Depois de resolver esses problemas, quaisquer outros problemas que você possa t ![Esquema mostrando os fluxos de dados entre o HTML, ações do usuário e estado](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.br.png) -> Não abordaremos aqui a parte em que os dados automaticamente acionam a atualização da visualização, pois está ligada a conceitos mais avançados de [Programação Reativa](https://en.wikipedia.org/wiki/Reactive_programming). É um bom assunto para um mergulho mais profundo. +> Não abordaremos aqui a parte em que os dados automaticamente acionam a atualização da visualização, pois está ligada a conceitos mais avançados de [Programação Reativa](https://en.wikipedia.org/wiki/Reactive_programming). É um bom assunto para aprofundar se você estiver interessado. -✅ Existem muitas bibliotecas por aí com diferentes abordagens para gerenciamento de estado, sendo o [Redux](https://redux.js.org) uma opção popular. Dê uma olhada nos conceitos e padrões usados, pois muitas vezes é uma boa maneira de aprender quais problemas potenciais você pode enfrentar em apps web grandes e como eles podem ser resolvidos. +✅ Existem muitas bibliotecas com diferentes abordagens para gerenciamento de estado, sendo o [Redux](https://redux.js.org) uma opção popular. Dê uma olhada nos conceitos e padrões usados, pois geralmente é uma boa maneira de aprender quais problemas potenciais você pode enfrentar em grandes aplicativos web e como eles podem ser resolvidos. ### Tarefa @@ -75,7 +75,7 @@ let state = { }; ``` -A ideia é *centralizar* todos os dados do nosso app em um único objeto de estado. Por enquanto, só temos `account` no estado, então isso não muda muito, mas cria um caminho para evoluções. +A ideia é *centralizar* todos os dados do nosso app em um único objeto de estado. Por enquanto, temos apenas `account` no estado, então isso não muda muito, mas cria um caminho para evoluções. Também precisamos atualizar as funções que o utilizam. Nas funções `register()` e `login()`, substitua `account = ...` por `state.account = ...`; @@ -87,13 +87,13 @@ const account = state.account; Essa refatoração por si só não trouxe muitas melhorias, mas a ideia era preparar o terreno para as próximas mudanças. -## Rastrear mudanças nos dados +## Acompanhar mudanças nos dados -Agora que colocamos em prática o objeto `state` para armazenar nossos dados, o próximo passo é centralizar as atualizações. O objetivo é facilitar o rastreamento de quaisquer mudanças e quando elas acontecem. +Agora que colocamos em prática o objeto `state` para armazenar nossos dados, o próximo passo é centralizar as atualizações. O objetivo é facilitar o acompanhamento de quaisquer mudanças e quando elas acontecem. -Para evitar que mudanças sejam feitas diretamente no objeto `state`, também é uma boa prática considerá-lo [*imutável*](https://en.wikipedia.org/wiki/Immutable_object), o que significa que ele não pode ser modificado de forma alguma. Isso também significa que você precisa criar um novo objeto de estado se quiser alterar algo nele. Ao fazer isso, você constrói uma proteção contra possíveis [efeitos colaterais](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) indesejados e abre possibilidades para novos recursos no seu app, como implementar desfazer/refazer, além de facilitar a depuração. Por exemplo, você poderia registrar todas as mudanças feitas no estado e manter um histórico das alterações para entender a origem de um bug. +Para evitar que alterações sejam feitas diretamente no objeto `state`, também é uma boa prática considerá-lo [*imutável*](https://en.wikipedia.org/wiki/Immutable_object), o que significa que ele não pode ser modificado de forma alguma. Isso também significa que você precisa criar um novo objeto de estado se quiser alterar algo nele. Ao fazer isso, você constrói uma proteção contra possíveis [efeitos colaterais](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) indesejados e abre possibilidades para novos recursos no seu app, como implementar desfazer/refazer, além de facilitar a depuração. Por exemplo, você poderia registrar todas as mudanças feitas no estado e manter um histórico das alterações para entender a origem de um bug. -Em JavaScript, você pode usar [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) para criar uma versão imutável de um objeto. Se você tentar fazer alterações em um objeto imutável, uma exceção será lançada. +No JavaScript, você pode usar [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) para criar uma versão imutável de um objeto. Se você tentar fazer alterações em um objeto imutável, uma exceção será lançada. ✅ Você sabe a diferença entre um objeto imutável *superficial* e *profundo*? Você pode ler sobre isso [aqui](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Nesta função, estamos criando um novo objeto de estado e copiando os dados do estado anterior usando o [*operador spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Em seguida, substituímos uma propriedade específica do objeto de estado com os novos dados usando a [notação de colchetes](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` para atribuição. Por fim, bloqueamos o objeto para evitar modificações usando `Object.freeze()`. Por enquanto, só temos a propriedade `account` armazenada no estado, mas com essa abordagem você pode adicionar quantas propriedades precisar no estado. +Nesta função, estamos criando um novo objeto de estado e copiando os dados do estado anterior usando o [*operador spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Em seguida, substituímos uma propriedade específica do objeto de estado com os novos dados usando a [notação de colchetes](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` para atribuição. Por fim, bloqueamos o objeto para evitar modificações usando `Object.freeze()`. Por enquanto, temos apenas a propriedade `account` armazenada no estado, mas com essa abordagem você pode adicionar quantas propriedades precisar no estado. Também atualizaremos a inicialização do `state` para garantir que o estado inicial seja congelado: @@ -143,31 +143,31 @@ function logout() { } ``` -Na função `updateDashboard()`, substitua o redirecionamento `return navigate('/login');` por `return logout();`; +Na função `updateDashboard()`, substitua o redirecionamento `return navigate('/login');` por `return logout()`; Tente registrar uma nova conta, fazer logout e login novamente para verificar se tudo ainda funciona corretamente. -> Dica: você pode observar todas as mudanças de estado adicionando `console.log(state)` no final de `updateState()` e abrindo o console nas ferramentas de desenvolvimento do navegador. +> Dica: você pode acompanhar todas as mudanças de estado adicionando `console.log(state)` no final de `updateState()` e abrindo o console nas ferramentas de desenvolvimento do seu navegador. ## Persistir o estado -A maioria dos apps web precisa persistir dados para funcionar corretamente. Todos os dados críticos geralmente são armazenados em um banco de dados e acessados por meio de uma API de servidor, como os dados da conta do usuário no nosso caso. Mas às vezes, também é interessante persistir alguns dados no app cliente que está sendo executado no navegador, para uma melhor experiência do usuário ou para melhorar o desempenho de carregamento. +A maioria dos aplicativos web precisa persistir dados para funcionar corretamente. Todos os dados críticos geralmente são armazenados em um banco de dados e acessados por meio de uma API de servidor, como os dados da conta do usuário no nosso caso. Mas às vezes, também é interessante persistir alguns dados no aplicativo cliente que está sendo executado no navegador, para uma melhor experiência do usuário ou para melhorar o desempenho de carregamento. Quando você deseja persistir dados no navegador, há algumas perguntas importantes que você deve se fazer: - *Os dados são sensíveis?* Você deve evitar armazenar qualquer dado sensível no cliente, como senhas de usuários. - *Por quanto tempo você precisa manter esses dados?* Você planeja acessar esses dados apenas para a sessão atual ou deseja que eles sejam armazenados para sempre? -Existem várias maneiras de armazenar informações dentro de um app web, dependendo do que você deseja alcançar. Por exemplo, você pode usar as URLs para armazenar uma consulta de pesquisa e torná-la compartilhável entre usuários. Você também pode usar [cookies HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) se os dados precisarem ser compartilhados com o servidor, como informações de [autenticação](https://en.wikipedia.org/wiki/Authentication). +Existem várias maneiras de armazenar informações dentro de um aplicativo web, dependendo do que você deseja alcançar. Por exemplo, você pode usar as URLs para armazenar uma consulta de pesquisa e torná-la compartilhável entre usuários. Você também pode usar [cookies HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) se os dados precisarem ser compartilhados com o servidor, como informações de [autenticação](https://en.wikipedia.org/wiki/Authentication). -Outra opção é usar uma das muitas APIs do navegador para armazenar dados. Duas delas são particularmente interessantes: +Outra opção é usar uma das muitas APIs de navegador para armazenar dados. Duas delas são particularmente interessantes: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): um [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) que permite persistir dados específicos do site atual entre diferentes sessões. Os dados salvos nele nunca expiram. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): um [armazenamento de chave/valor](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) que permite persistir dados específicos do site atual entre diferentes sessões. Os dados salvos nele nunca expiram. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funciona da mesma forma que o `localStorage`, exceto que os dados armazenados nele são apagados quando a sessão termina (quando o navegador é fechado). Observe que ambas as APIs permitem apenas armazenar [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Se você quiser armazenar objetos complexos, precisará serializá-los no formato [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) usando [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Se você quiser criar um app web que não funcione com um servidor, também é possível criar um banco de dados no cliente usando a API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Esta é reservada para casos de uso avançados ou se você precisar armazenar uma quantidade significativa de dados, pois é mais complexa de usar. +✅ Se você quiser criar um aplicativo web que não funcione com um servidor, também é possível criar um banco de dados no cliente usando a API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Essa opção é reservada para casos de uso avançados ou se você precisar armazenar uma quantidade significativa de dados, pois é mais complexa de usar. ### Tarefa @@ -177,7 +177,7 @@ Queremos que nossos usuários permaneçam logados até que cliquem explicitament const storageKey = 'savedAccount'; ``` -Em seguida, adicione esta linha ao final da função `updateState()`: +Em seguida, adicione esta linha no final da função `updateState()`: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); Com isso, os dados da conta do usuário serão persistidos e sempre atualizados, já que centralizamos anteriormente todas as atualizações de estado. É aqui que começamos a colher os benefícios de todas as nossas refatorações anteriores 🙂. -Como os dados são salvos, também precisamos cuidar de restaurá-los quando o app for carregado. Como começaremos a ter mais código de inicialização, pode ser uma boa ideia criar uma nova função `init`, que também inclui nosso código anterior no final de `app.js`: +Como os dados estão sendo salvos, também precisamos cuidar de restaurá-los quando o app for carregado. Como começaremos a ter mais código de inicialização, pode ser uma boa ideia criar uma nova função `init`, que também inclui nosso código anterior no final de `app.js`: ```js function init() { @@ -204,7 +204,7 @@ init(); Aqui, recuperamos os dados salvos e, se houver algum, atualizamos o estado de acordo. É importante fazer isso *antes* de atualizar a rota, pois pode haver código que depende do estado durante a atualização da página. -Também podemos tornar a página *Dashboard* a página padrão do nosso app, já que agora estamos persistindo os dados da conta. Se nenhum dado for encontrado, o painel cuida de redirecionar para a página de *Login* de qualquer forma. Em `updateRoute()`, substitua o fallback `return navigate('/login');` por `return navigate('/dashboard');`. +Também podemos tornar a página *Dashboard* a página padrão da nossa aplicação, já que agora estamos persistindo os dados da conta. Se nenhum dado for encontrado, o painel cuida de redirecionar para a página de *Login* de qualquer forma. Em `updateRoute()`, substitua o fallback `return navigate('/login');` por `return navigate('/dashboard');`. Agora faça login no app e tente atualizar a página. Você deve permanecer no painel. Com essa atualização, resolvemos todos os nossos problemas iniciais... @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Agora tente atualizar a página do painel no navegador. O que acontece? Você vê a nova transação? +Agora tente atualizar sua página de painel no navegador. O que acontece? Você vê a nova transação? -O estado é persistido indefinidamente graças ao `localStorage`, mas isso também significa que ele nunca é atualizado até que você saia do app e entre novamente! +O estado é persistido indefinidamente graças ao `localStorage`, mas isso também significa que ele nunca é atualizado até que você saia do app e faça login novamente! Uma possível estratégia para corrigir isso é recarregar os dados da conta toda vez que o painel for carregado, para evitar dados desatualizados. @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Este método verifica se estamos atualmente logados e então recarrega os dados da conta do servidor. +Este método verifica se estamos atualmente logados e, em seguida, recarrega os dados da conta do servidor. Crie outra função chamada `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Esta função atualiza os dados da conta e cuida de atualizar o HTML da página do painel. É o que precisamos chamar quando a rota do painel for carregada. Atualize a definição da rota com: +Esta função atualiza os dados da conta e, em seguida, cuida de atualizar o HTML da página do painel. É o que precisamos chamar quando a rota do painel for carregada. Atualize a definição da rota com: ```js const routes = { @@ -267,7 +267,7 @@ const routes = { }; ``` -Agora tente atualizar o painel. Ele deve exibir os dados da conta atualizados. +Agora tente recarregar o painel, ele deve exibir os dados da conta atualizados. --- @@ -278,10 +278,10 @@ Agora que recarregamos os dados da conta toda vez que o painel é carregado, voc Tente trabalhar em equipe para alterar o que é salvo e carregado do `localStorage` para incluir apenas o que é absolutamente necessário para o app funcionar. ## Quiz Pós-Aula - [Quiz pós-aula](https://ff-quizzes.netlify.app/web/quiz/48) ## Tarefa + [Implementar o diálogo "Adicionar transação"](assignment.md) Aqui está um exemplo do resultado após concluir a tarefa: @@ -291,4 +291,4 @@ Aqui está um exemplo do resultado após concluir a tarefa: --- **Aviso Legal**: -Este documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automatizadas podem conter erros ou imprecisões. O documento original em seu idioma nativo deve ser considerado a fonte autoritativa. Para informações críticas, recomenda-se a tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações equivocadas decorrentes do uso desta tradução. \ No newline at end of file +Este documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos para garantir a precisão, esteja ciente de que traduções automáticas podem conter erros ou imprecisões. O documento original em seu idioma nativo deve ser considerado a fonte autoritativa. Para informações críticas, recomenda-se a tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações equivocadas decorrentes do uso desta tradução. \ No newline at end of file diff --git a/translations/cs/7-bank-project/4-state-management/README.md b/translations/cs/7-bank-project/4-state-management/README.md index 711f2c903..f4a4dbbfd 100644 --- a/translations/cs/7-bank-project/4-state-management/README.md +++ b/translations/cs/7-bank-project/4-state-management/README.md @@ -1,27 +1,27 @@ # Vytvoření bankovní aplikace, část 4: Koncepty správy stavu -## Kvíz před přednáškou +## Kvíz před lekcí -[Kvíz před přednáškou](https://ff-quizzes.netlify.app/web/quiz/47) +[Kvíz před lekcí](https://ff-quizzes.netlify.app/web/quiz/47) ### Úvod -Jak webová aplikace roste, stává se stále obtížnější sledovat všechny datové toky. Který kód získává data, která stránka je spotřebovává, kde a kdy je třeba je aktualizovat... snadno se dostanete k chaotickému kódu, který je obtížné udržovat. To platí zejména tehdy, když potřebujete sdílet data mezi různými stránkami vaší aplikace, například uživatelská data. Koncept *správy stavu* vždy existoval ve všech typech programů, ale jak webové aplikace stále rostou na složitosti, stává se klíčovým bodem, o kterém je třeba během vývoje přemýšlet. +Jak webová aplikace roste, stává se stále obtížnější sledovat všechny datové toky. Který kód získává data, která stránka je spotřebovává, kde a kdy je třeba je aktualizovat... snadno se dostanete k chaotickému kódu, který je těžké udržovat. To platí zejména tehdy, když potřebujete sdílet data mezi různými stránkami vaší aplikace, například uživatelská data. Koncept *správy stavu* existuje ve všech typech programů, ale jak webové aplikace stále rostou na složitosti, stává se klíčovým bodem, o kterém je třeba během vývoje přemýšlet. V této poslední části se podíváme na aplikaci, kterou jsme vytvořili, abychom přehodnotili, jak je spravován stav, což umožní podporu obnovení prohlížeče kdykoli a zachování dat mezi uživatelskými relacemi. ### Předpoklady -Pro tuto lekci musíte mít dokončenou část [získávání dat](../3-data/README.md) webové aplikace. Také musíte nainstalovat [Node.js](https://nodejs.org) a [spustit server API](../api/README.md) lokálně, abyste mohli spravovat data účtu. +Musíte mít dokončenou část [získávání dat](../3-data/README.md) webové aplikace pro tuto lekci. Také musíte nainstalovat [Node.js](https://nodejs.org) a [spustit server API](../api/README.md) lokálně, abyste mohli spravovat data účtu. Můžete otestovat, zda server běží správně, spuštěním tohoto příkazu v terminálu: @@ -34,30 +34,30 @@ curl http://localhost:5000/api ## Přehodnocení správy stavu -V [předchozí lekci](../3-data/README.md) jsme představili základní koncept stavu v naší aplikaci s globální proměnnou `account`, která obsahuje bankovní data aktuálně přihlášeného uživatele. Nicméně naše současná implementace má určité nedostatky. Zkuste obnovit stránku, když jste na dashboardu. Co se stane? +V [předchozí lekci](../3-data/README.md) jsme představili základní koncept stavu v naší aplikaci pomocí globální proměnné `account`, která obsahuje bankovní data aktuálně přihlášeného uživatele. Nicméně naše současná implementace má určité nedostatky. Zkuste obnovit stránku, když jste na dashboardu. Co se stane? Existují 3 problémy se současným kódem: - Stav není zachován, protože obnovení prohlížeče vás vrátí na přihlašovací stránku. -- Existuje několik funkcí, které upravují stav. Jak aplikace roste, může být obtížné sledovat změny a snadno zapomenete aktualizovat jednu z nich. +- Existuje několik funkcí, které stav mění. Jak aplikace roste, může být obtížné sledovat změny a snadno se zapomene na aktualizaci jedné z nich. - Stav není vyčištěn, takže když kliknete na *Odhlásit se*, data účtu tam stále jsou, i když jste na přihlašovací stránce. Mohli bychom aktualizovat náš kód, abychom tyto problémy řešili jeden po druhém, ale vytvořilo by to více duplicitního kódu a učinilo aplikaci složitější a obtížněji udržovatelnou. Nebo bychom se mohli na pár minut zastavit a přehodnotit naši strategii. > Jaké problémy se zde vlastně snažíme vyřešit? -[Správa stavu](https://en.wikipedia.org/wiki/State_management) je o nalezení dobrého přístupu k řešení těchto dvou konkrétních problémů: +[Správa stavu](https://en.wikipedia.org/wiki/State_management) je především o nalezení dobrého přístupu k řešení těchto dvou konkrétních problémů: - Jak udržet datové toky v aplikaci srozumitelné? -- Jak udržet stavová data vždy synchronizovaná s uživatelským rozhraním (a naopak)? +- Jak udržet data stavu vždy synchronizovaná s uživatelským rozhraním (a naopak)? Jakmile se o tyto problémy postaráte, jakékoli další problémy, které byste mohli mít, mohou být buď již vyřešeny, nebo se staly snadněji řešitelnými. Existuje mnoho možných přístupů k řešení těchto problémů, ale zvolíme běžné řešení, které spočívá v **centralizaci dat a způsobů jejich změny**. Datové toky by vypadaly takto: -![Schéma zobrazující datové toky mezi HTML, uživatelskými akcemi a stavem](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.cs.png) +![Schéma ukazující datové toky mezi HTML, uživatelskými akcemi a stavem](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.cs.png) > Zde nebudeme pokrývat část, kde data automaticky spouštějí aktualizaci zobrazení, protože je spojena s pokročilejšími koncepty [reaktivního programování](https://en.wikipedia.org/wiki/Reactive_programming). Je to dobré téma pro hlubší studium, pokud máte zájem. -✅ Existuje mnoho knihoven s různými přístupy ke správě stavu, [Redux](https://redux.js.org) je populární volbou. Podívejte se na koncepty a vzory, které používá, protože často poskytují dobrý přehled o potenciálních problémech, kterým můžete čelit ve velkých webových aplikacích, a o tom, jak je lze vyřešit. +✅ Existuje mnoho knihoven s různými přístupy ke správě stavu, [Redux](https://redux.js.org) je populární volbou. Podívejte se na koncepty a vzory, které používá, protože často poskytují dobrý způsob, jak se naučit, jaké potenciální problémy můžete čelit ve velkých webových aplikacích a jak je lze vyřešit. ### Úkol @@ -75,7 +75,7 @@ let state = { }; ``` -Myšlenkou je *centralizovat* všechna data naší aplikace do jediného objektu stavu. Zatím máme ve stavu pouze `account`, takže se toho moc nezmění, ale vytváříme cestu pro budoucí rozšíření. +Myšlenkou je *centralizovat* všechna data naší aplikace do jednoho objektu stavu. Zatím máme ve stavu pouze `account`, takže se toho moc nezmění, ale vytváří to cestu pro budoucí rozšíření. Musíme také aktualizovat funkce, které jej používají. Ve funkcích `register()` a `login()` nahraďte `account = ...` za `state.account = ...`; @@ -89,9 +89,9 @@ Tento refaktoring sám o sobě nepřinesl mnoho zlepšení, ale myšlenkou bylo ## Sledování změn dat -Nyní, když jsme vytvořili objekt `state` pro ukládání našich dat, dalším krokem je centralizace aktualizací. Cílem je usnadnit sledování jakýchkoli změn a kdy k nim dochází. +Nyní, když jsme zavedli objekt `state` pro ukládání našich dat, dalším krokem je centralizace aktualizací. Cílem je usnadnit sledování jakýchkoli změn a kdy k nim dochází. -Aby se zabránilo změnám objektu `state`, je také dobré považovat jej za [*neměnný*](https://en.wikipedia.org/wiki/Immutable_object), což znamená, že jej nelze vůbec upravovat. To také znamená, že musíte vytvořit nový objekt stavu, pokud chcete něco změnit. Tímto způsobem vytváříte ochranu proti potenciálně nežádoucím [vedlejším účinkům](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) a otevíráte možnosti pro nové funkce ve vaší aplikaci, jako je implementace undo/redo, a zároveň usnadňujete ladění. Například byste mohli zaznamenávat každou změnu provedenou ve stavu a uchovávat historii změn, abyste pochopili zdroj chyby. +Aby se zabránilo změnám objektu `state`, je také dobré považovat jej za [*neměnný*](https://en.wikipedia.org/wiki/Immutable_object), což znamená, že jej nelze vůbec upravovat. To také znamená, že musíte vytvořit nový objekt stavu, pokud chcete něco změnit. Tímto způsobem si vytvoříte ochranu proti potenciálně nežádoucím [vedlejším účinkům](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) a otevřete možnosti pro nové funkce ve vaší aplikaci, jako je implementace undo/redo, a zároveň usnadníte ladění. Například byste mohli zaznamenávat každou změnu provedenou ve stavu a uchovávat historii změn, abyste pochopili zdroj chyby. V JavaScriptu můžete použít [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) k vytvoření neměnné verze objektu. Pokud se pokusíte provést změny neměnného objektu, bude vyvolána výjimka. @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -V této funkci vytváříme nový objekt stavu a kopírujeme data z předchozího stavu pomocí [*operátoru rozbalení (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Poté přepisujeme konkrétní vlastnost objektu stavu novými daty pomocí [notace hranatých závorek](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` pro přiřazení. Nakonec objekt uzamkneme, aby se zabránilo úpravám pomocí `Object.freeze()`. Zatím máme ve stavu pouze vlastnost `account`, ale s tímto přístupem můžete do stavu přidat tolik vlastností, kolik potřebujete. +V této funkci vytváříme nový objekt stavu a kopírujeme data z předchozího stavu pomocí [*operátoru spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Poté přepisujeme konkrétní vlastnost objektu stavu novými daty pomocí [notace hranatých závorek](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` pro přiřazení. Nakonec objekt uzamkneme, aby se zabránilo úpravám pomocí `Object.freeze()`. Zatím máme ve stavu pouze vlastnost `account`, ale s tímto přístupem můžete do stavu přidat tolik vlastností, kolik potřebujete. Také aktualizujeme inicializaci `state`, abychom zajistili, že počáteční stav bude také zmrazen: @@ -126,7 +126,7 @@ Poté aktualizujte funkci `register` nahrazením přiřazení `state.account = r updateState('account', result); ``` -Uděláme totéž s funkcí `login`, nahrazením `state.account = data;` za: +Udělejte totéž s funkcí `login`, nahrazením `state.account = data;` za: ```js updateState('account', data); @@ -151,27 +151,27 @@ Zkuste zaregistrovat nový účet, odhlásit se a znovu se přihlásit, abyste o ## Zachování stavu -Většina webových aplikací potřebuje uchovávat data, aby mohla správně fungovat. Všechna kritická data jsou obvykle uložena v databázi a přistupuje se k nim prostřednictvím serverového API, například k datům uživatelského účtu v našem případě. Ale někdy je také zajímavé uchovávat některá data na klientské aplikaci, která běží ve vašem prohlížeči, pro lepší uživatelský zážitek nebo pro zlepšení výkonu načítání. +Většina webových aplikací potřebuje uchovávat data, aby mohla správně fungovat. Všechna kritická data jsou obvykle uložena v databázi a přistupuje se k nim prostřednictvím serverového API, jako jsou například data uživatelského účtu v našem případě. Ale někdy je také zajímavé uchovávat některá data na klientské aplikaci, která běží ve vašem prohlížeči, pro lepší uživatelský zážitek nebo pro zlepšení výkonu načítání. -Když chcete uchovávat data ve svém prohlížeči, existuje několik důležitých otázek, které byste si měli položit: +Když chcete uchovávat data ve vašem prohlížeči, existuje několik důležitých otázek, které byste si měli položit: - *Jsou data citlivá?* Měli byste se vyhnout ukládání jakýchkoli citlivých dat na klienta, jako jsou hesla uživatelů. -- *Jak dlouho potřebujete tato data uchovávat?* Plánujete přístup k těmto datům pouze pro aktuální relaci, nebo je chcete uchovávat navždy? +- *Jak dlouho potřebujete tato data uchovávat?* Plánujete přistupovat k těmto datům pouze během aktuální relace, nebo je chcete uchovávat navždy? -Existuje několik způsobů, jak ukládat informace uvnitř webové aplikace, v závislosti na tom, čeho chcete dosáhnout. Například můžete použít URL k uložení vyhledávacího dotazu a učinit jej sdílitelným mezi uživateli. Můžete také použít [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), pokud je třeba data sdílet se serverem, například informace o [autentizaci](https://en.wikipedia.org/wiki/Authentication). +Existuje několik způsobů, jak ukládat informace uvnitř webové aplikace, v závislosti na tom, čeho chcete dosáhnout. Například můžete použít URL k uložení vyhledávacího dotazu a učinit jej sdílitelným mezi uživateli. Můžete také použít [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), pokud je potřeba data sdílet se serverem, například informace o [autentizaci](https://en.wikipedia.org/wiki/Authentication). Další možností je použití jedné z mnoha API prohlížeče pro ukládání dat. Dvě z nich jsou obzvláště zajímavé: - [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), který umožňuje uchovávat data specifická pro aktuální webovou stránku mezi různými relacemi. Data uložená v něm nikdy nevyprší. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funguje stejně jako `localStorage`, kromě toho, že data uložená v něm jsou vymazána, když relace skončí (když se prohlížeč zavře). +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funguje stejně jako `localStorage`, kromě toho, že data uložená v něm jsou vymazána, když relace skončí (když je prohlížeč zavřen). Všimněte si, že obě tyto API umožňují ukládat pouze [řetězce](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Pokud chcete ukládat složité objekty, budete je muset serializovat do formátu [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) pomocí [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Pokud chcete vytvořit webovou aplikaci, která nepracuje se serverem, je také možné vytvořit databázi na klientovi pomocí [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Toto je vyhrazeno pro pokročilé případy použití nebo pokud potřebujete ukládat významné množství dat, protože je složitější na použití. +✅ Pokud chcete vytvořit webovou aplikaci, která nepracuje se serverem, je také možné vytvořit databázi na klientovi pomocí [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Tato možnost je vyhrazena pro pokročilé případy použití nebo pokud potřebujete ukládat významné množství dat, protože je složitější na použití. ### Úkol -Chceme, aby naši uživatelé zůstali přihlášeni, dokud explicitně nekliknou na tlačítko *Odhlásit se*, takže použijeme `localStorage` k ukládání dat účtu. Nejprve definujeme klíč, který použijeme k ukládání našich dat. +Chceme, aby naši uživatelé zůstali přihlášeni, dokud explicitně nekliknou na tlačítko *Odhlásit se*, takže použijeme `localStorage` k ukládání dat účtu. Nejprve definujme klíč, který použijeme k ukládání našich dat. ```js const storageKey = 'savedAccount'; @@ -202,15 +202,15 @@ function init() { init(); ``` -Zde získáváme uložená data a pokud nějaká existují, aktualizujeme stav odpovídajícím způsobem. Je důležité to udělat *před* aktualizací trasy, protože během aktualizace stránky může být kód závislý na stavu. +Zde získáváme uložená data a pokud nějaká existují, aktualizujeme stav odpovídajícím způsobem. Je důležité to udělat *před* aktualizací trasy, protože může existovat kód, který se spoléhá na stav během aktualizace stránky. Můžeme také udělat stránku *Dashboard* výchozí stránkou naší aplikace, protože nyní uchováváme data účtu. Pokud žádná data nejsou nalezena, dashboard se postará o přesměrování na stránku *Login*. V `updateRoute()` nahraďte výchozí `return navigate('/login');` za `return navigate('/dashboard');`. -Nyní se přihlaste do aplikace a zkuste obnovit stránku. Měli byste zůstat na dashboardu. S touto aktualizací jsme se postarali o všechny naše počáteční problémy... +Nyní se přihlaste do aplikace a zkuste obnovit stránku. Měli byste zůstat na dashboardu. Tímto jsme vyřešili všechny naše počáteční problémy... ## Aktualizace dat -...Ale možná jsme také vytvořili nový problém. Ups! +...Ale možná jsme také vytvořili nový problém. Oops! Přejděte na dashboard pomocí účtu `test`, poté spusťte tento příkaz v terminálu, abyste vytvořili novou transakci: @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Zkuste nyní obnovit stránku dashboardu v prohlížeči. Co se stane? Vidíte novou transakci? +Zkuste nyní obnovit stránku dashboardu ve vašem prohlížeči. Co se stane? Vidíte novou transakci? -Stav je uchováván neomezeně díky `localStorage`, ale to také znamená, že se nikdy neaktualizuje, dokud se z aplikace neodhlásíte a znovu nepřihlásíte! +Stav je uchováván neomezeně díky `localStorage`, ale to také znamená, že se nikdy neaktualizuje, dokud se neodhlásíte z aplikace a znovu se nepřihlásíte! Jednou z možných strategií, jak to opravit, je znovu načíst data účtu pokaždé, když je dashboard načten, aby se zabránilo zastaralým datům. @@ -258,7 +258,7 @@ async function refresh() { } ``` -Tato funkce aktualizuje data účtu a poté se postará o aktualizaci HTML stránky dashboardu. To je to, co potřebujeme zavolat, když je načtena trasa dashboardu. Aktualizujte definici trasy: +Tato funkce aktualizuje data účtu a poté se postará o aktualizaci HTML stránky dashboardu. To je to, co potřebujeme zavolat, když je načtena trasa dashboardu. Aktualizujte definici trasy pomocí: ```js const routes = { @@ -275,20 +275,20 @@ Zkuste nyní obnovit dashboard, měl by zobrazit aktualizovaná data účtu. Nyní, když znovu načítáme data účtu pokaždé, když je dashboard načten, myslíte si, že stále potřebujeme uchovávat *všechna data účtu*? -Zkuste společně upravit, co je ukládáno a načítáno z `localStorage`, aby zahrnovalo pouze to, co je absolutně nezbytné pro fungování aplikace. +Zkuste společně změnit, co je ukládáno a načítáno z `localStorage`, aby obsahovalo pouze to, co je absolutně nezbytné pro fungování aplikace. -## Kvíz po přednášce +## Kvíz po lekci +[Post-přednáškový kvíz](https://ff-quizzes.netlify.app/web/quiz/48) -[Kvíz po přednášce](https://ff-quizzes.netlify.app/web/quiz/48) +## Úkol -## Zadání -[Implementace dialogu "Přidat transakci"](assignment.md) +[Implementujte dialog "Přidat transakci"](assignment.md) -Zde je ukázkový výsledek po dokončení úkolu: +Zde je příklad výsledku po dokončení úkolu: ![Snímek obrazovky zobrazující příklad dialogu "Přidat transakci"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.cs.png) --- **Prohlášení**: -Tento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o co největší přesnost, mějte prosím na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za závazný zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné výklady vyplývající z použití tohoto překladu. \ No newline at end of file +Tento dokument byl přeložen pomocí služby AI pro překlad [Co-op Translator](https://github.com/Azure/co-op-translator). I když se snažíme o přesnost, mějte prosím na paměti, že automatizované překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace se doporučuje profesionální lidský překlad. Neodpovídáme za žádná nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu. \ No newline at end of file diff --git a/translations/da/7-bank-project/4-state-management/README.md b/translations/da/7-bank-project/4-state-management/README.md index a3eda2569..7d40519b7 100644 --- a/translations/da/7-bank-project/4-state-management/README.md +++ b/translations/da/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# Byg en Bankapp Del 4: Koncepter inden for State Management +# Byg en bankapp del 4: Koncepter inden for tilstandsadministration ## Quiz før forelæsning @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Introduktion -Når en webapplikation vokser, bliver det en udfordring at holde styr på alle dataflows. Hvilken kode henter data, hvilken side bruger det, hvor og hvornår skal det opdateres...det er nemt at ende med rodet kode, der er svær at vedligeholde. Dette er især tilfældet, når du skal dele data mellem forskellige sider i din app, for eksempel brugerdata. Konceptet *state management* har altid eksisteret i alle slags programmer, men efterhånden som webapps bliver mere komplekse, er det nu et centralt punkt at tænke over under udviklingen. +Efterhånden som en webapplikation vokser, bliver det en udfordring at holde styr på alle dataflows. Hvilken kode henter data, hvilken side bruger det, hvor og hvornår skal det opdateres...det er nemt at ende med rodet kode, der er svær at vedligeholde. Dette er især tilfældet, når du skal dele data mellem forskellige sider i din app, for eksempel brugerdata. Konceptet *tilstandsadministration* har altid eksisteret i alle slags programmer, men efterhånden som webapps bliver mere komplekse, er det nu et nøglepunkt at tænke over under udviklingen. -I denne sidste del vil vi gennemgå den app, vi har bygget, for at genoverveje, hvordan state håndteres, så vi kan understøtte browseropdatering på ethvert tidspunkt og bevare data på tværs af brugersessioner. +I denne sidste del vil vi gennemgå den app, vi har bygget, for at genoverveje, hvordan tilstanden administreres, så vi kan understøtte browseropdatering på ethvert tidspunkt og bevare data på tværs af brugersessioner. ### Forudsætninger -Du skal have gennemført [datahentning](../3-data/README.md)-delen af webappen for denne lektion. Du skal også installere [Node.js](https://nodejs.org) og [køre server-API'et](../api/README.md) lokalt, så du kan administrere kontodata. +Du skal have gennemført [datahentning](../3-data/README.md)-delen af webappen for denne lektion. Du skal også installere [Node.js](https://nodejs.org) og [køre server-API'en](../api/README.md) lokalt, så du kan administrere kontodata. Du kan teste, om serveren kører korrekt, ved at udføre denne kommando i en terminal: @@ -32,32 +32,32 @@ curl http://localhost:5000/api --- -## Genovervej state management +## Genovervej tilstandsadministration -I [den forrige lektion](../3-data/README.md) introducerede vi et grundlæggende koncept for state i vores app med den globale `account`-variabel, som indeholder bankdata for den aktuelt loggede bruger. Men vores nuværende implementering har nogle mangler. Prøv at opdatere siden, når du er på dashboardet. Hvad sker der? +I [den forrige lektion](../3-data/README.md) introducerede vi et grundlæggende koncept for tilstand i vores app med den globale `account`-variabel, som indeholder bankdata for den aktuelt loggede bruger. Men vores nuværende implementering har nogle mangler. Prøv at opdatere siden, når du er på dashboardet. Hvad sker der? Der er tre problemer med den nuværende kode: -- State bliver ikke bevaret, da en browseropdatering sender dig tilbage til login-siden. -- Der er flere funktioner, der ændrer state. Efterhånden som appen vokser, kan det gøre det svært at spore ændringer, og det er nemt at glemme at opdatere en. -- State bliver ikke ryddet op, så når du klikker på *Logout*, er kontodata stadig der, selvom du er på login-siden. +- Tilstanden gemmes ikke, da en browseropdatering sender dig tilbage til login-siden. +- Der er flere funktioner, der ændrer tilstanden. Efterhånden som appen vokser, kan det gøre det svært at spore ændringerne, og det er nemt at glemme at opdatere en. +- Tilstanden ryddes ikke op, så når du klikker på *Log ud*, er kontodataene stadig der, selvom du er på login-siden. Vi kunne opdatere vores kode for at tackle disse problemer ét ad gangen, men det ville skabe mere kodegentagelse og gøre appen mere kompleks og svær at vedligeholde. Eller vi kunne tage et øjeblik og genoverveje vores strategi. > Hvilke problemer prøver vi egentlig at løse her? -[State management](https://en.wikipedia.org/wiki/State_management) handler om at finde en god tilgang til at løse disse to specifikke problemer: +[Tilstandsadministration](https://en.wikipedia.org/wiki/State_management) handler om at finde en god tilgang til at løse disse to specifikke problemer: -- Hvordan holder vi dataflows i en app forståelige? -- Hvordan holder vi state-data altid i sync med brugergrænsefladen (og omvendt)? +- Hvordan holder man dataflows i en app forståelige? +- Hvordan holder man tilstandsdata altid synkroniseret med brugergrænsefladen (og omvendt)? -Når du har taget hånd om disse, kan andre problemer enten allerede være løst eller være blevet lettere at løse. Der er mange mulige tilgange til at løse disse problemer, men vi vil vælge en almindelig løsning, der består i **at centralisere data og måderne at ændre dem på**. Dataflows ville se sådan ud: +Når du har taget hånd om disse, kan andre problemer, du måtte have, enten allerede være løst eller være blevet lettere at løse. Der er mange mulige tilgange til at løse disse problemer, men vi vil vælge en almindelig løsning, der består i **at centralisere data og måderne at ændre dem på**. Dataflows ville se sådan ud: -![Skema, der viser dataflows mellem HTML, brugerhandlinger og state](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.da.png) +![Skema, der viser dataflows mellem HTML, brugerhandlinger og tilstand](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.da.png) -> Vi vil ikke dække den del, hvor data automatisk udløser opdatering af visningen, da det er knyttet til mere avancerede koncepter inden for [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming). Det er et godt emne til en dybere dykning. +> Vi vil ikke dække den del, hvor data automatisk udløser visningsopdateringen, da det er knyttet til mere avancerede begreber inden for [reaktiv programmering](https://en.wikipedia.org/wiki/Reactive_programming). Det er et godt emne at dykke ned i, hvis du er klar til en dybere forståelse. -✅ Der findes mange biblioteker med forskellige tilgange til state management, hvor [Redux](https://redux.js.org) er en populær mulighed. Tag et kig på de koncepter og mønstre, der bruges, da det ofte er en god måde at lære om potentielle problemer, du kan stå over for i store webapps, og hvordan de kan løses. +✅ Der findes mange biblioteker med forskellige tilgange til tilstandsadministration, hvor [Redux](https://redux.js.org) er en populær mulighed. Tag et kig på de koncepter og mønstre, der bruges, da det ofte er en god måde at lære, hvilke potentielle problemer du kan stå over for i store webapps, og hvordan de kan løses. ### Opgave @@ -75,7 +75,7 @@ let state = { }; ``` -Ideen er at *centralisere* alle vores appdata i et enkelt state-objekt. Vi har kun `account` i state lige nu, så det ændrer ikke meget, men det skaber en vej for fremtidige udvidelser. +Ideen er at *centralisere* alle vores appdata i et enkelt tilstandsobjekt. Vi har kun `account` i tilstanden lige nu, så det ændrer ikke meget, men det skaber en vej for fremtidige udviklinger. Vi skal også opdatere de funktioner, der bruger det. I funktionerne `register()` og `login()` skal du erstatte `account = ...` med `state.account = ...`; @@ -91,11 +91,11 @@ Denne refaktorering i sig selv har ikke bragt mange forbedringer, men ideen var Nu hvor vi har oprettet `state`-objektet til at gemme vores data, er næste skridt at centralisere opdateringerne. Målet er at gøre det lettere at holde styr på eventuelle ændringer og hvornår de sker. -For at undgå, at der foretages ændringer i `state`-objektet, er det også en god praksis at betragte det som [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), hvilket betyder, at det slet ikke kan ændres. Det betyder også, at du skal oprette et nyt state-objekt, hvis du vil ændre noget i det. Ved at gøre dette bygger du en beskyttelse mod potentielt uønskede [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) og åbner op for nye funktioner i din app, som f.eks. implementering af undo/redo, samtidig med at det bliver lettere at debugge. For eksempel kunne du logge hver ændring, der foretages i state, og holde en historik over ændringerne for at forstå kilden til en fejl. +For at undgå, at der foretages ændringer i `state`-objektet, er det også en god praksis at betragte det som [*uændret*](https://en.wikipedia.org/wiki/Immutable_object), hvilket betyder, at det slet ikke kan ændres. Det betyder også, at du skal oprette et nyt tilstandsobjekt, hvis du vil ændre noget i det. Ved at gøre dette bygger du en beskyttelse mod potentielt uønskede [sideeffekter](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) og åbner op for muligheder for nye funktioner i din app, såsom implementering af fortryd/gendan, samtidig med at det bliver lettere at fejlfinde. For eksempel kunne du logge hver ændring, der foretages i tilstanden, og holde en historik over ændringerne for at forstå kilden til en fejl. -I JavaScript kan du bruge [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) til at oprette en immutable version af et objekt. Hvis du forsøger at foretage ændringer i et immutable objekt, vil der blive rejst en undtagelse. +I JavaScript kan du bruge [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) til at oprette en uændret version af et objekt. Hvis du forsøger at foretage ændringer i et uændret objekt, vil der blive rejst en undtagelse. -✅ Kender du forskellen mellem et *shallow* og et *deep* immutable objekt? Du kan læse om det [her](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Kender du forskellen mellem et *overfladisk* og et *dybt* uændret objekt? Du kan læse om det [her](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Opgave @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -I denne funktion opretter vi et nyt state-objekt og kopierer data fra det tidligere state ved hjælp af [*spread (`...`) operatoren*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Derefter overskriver vi en bestemt egenskab i state-objektet med de nye data ved hjælp af [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` til tildeling. Til sidst låser vi objektet for at forhindre ændringer ved hjælp af `Object.freeze()`. Vi har kun egenskaben `account` gemt i state lige nu, men med denne tilgang kan du tilføje så mange egenskaber, som du har brug for i state. +I denne funktion opretter vi et nyt tilstandsobjekt og kopierer data fra den tidligere tilstand ved hjælp af [*spread (`...`) operatoren*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Derefter overskriver vi en bestemt egenskab i tilstandsobjektet med de nye data ved hjælp af [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` til tildeling. Til sidst låser vi objektet for at forhindre ændringer ved hjælp af `Object.freeze()`. Vi har kun egenskaben `account` gemt i tilstanden lige nu, men med denne tilgang kan du tilføje så mange egenskaber, som du har brug for i tilstanden. -Vi opdaterer også `state`-initialiseringen for at sikre, at den oprindelige state også er frosset: +Vi opdaterer også `state`-initialiseringen for at sikre, at den oprindelige tilstand også er låst: ```js let state = Object.freeze({ @@ -120,7 +120,7 @@ let state = Object.freeze({ }); ``` -Derefter opdaterer vi `register`-funktionen ved at erstatte `state.account = result;`-tildelingen med: +Derefter opdaterer vi `register`-funktionen ved at erstatte tildelingen `state.account = result;` med: ```js updateState('account', result); @@ -132,7 +132,7 @@ Gør det samme med `login`-funktionen ved at erstatte `state.account = data;` me updateState('account', data); ``` -Vi benytter nu lejligheden til at løse problemet med, at kontodata ikke bliver ryddet, når brugeren klikker på *Logout*. +Vi vil nu benytte lejligheden til at løse problemet med, at kontodata ikke ryddes, når brugeren klikker på *Log ud*. Opret en ny funktion `logout()`: @@ -143,47 +143,47 @@ function logout() { } ``` -I `updateDashboard()` skal du erstatte omdirigeringen `return navigate('/login');` med `return logout();` +I `updateDashboard()` skal du erstatte omdirigeringen `return navigate('/login');` med `return logout();`; Prøv at registrere en ny konto, logge ud og logge ind igen for at kontrollere, at alt stadig fungerer korrekt. -> Tip: Du kan se alle state-ændringer ved at tilføje `console.log(state)` nederst i `updateState()` og åbne konsollen i din browsers udviklingsværktøjer. +> Tip: Du kan se alle tilstandsændringer ved at tilføje `console.log(state)` nederst i `updateState()` og åbne konsollen i din browsers udviklingsværktøjer. -## Bevar state +## Gem tilstanden -De fleste webapps har brug for at bevare data for at kunne fungere korrekt. Alle kritiske data gemmes normalt i en database og tilgås via et server-API, som f.eks. brugerens kontodata i vores tilfælde. Men nogle gange kan det også være interessant at bevare nogle data i klientappen, der kører i din browser, for at give en bedre brugeroplevelse eller forbedre indlæsningshastigheden. +De fleste webapps har brug for at gemme data for at kunne fungere korrekt. Alle kritiske data gemmes normalt i en database og tilgås via en server-API, som brugerens kontodata i vores tilfælde. Men nogle gange er det også interessant at gemme nogle data i klientappen, der kører i din browser, for at give en bedre brugeroplevelse eller forbedre indlæsningsydelsen. -Når du vil bevare data i din browser, er der nogle vigtige spørgsmål, du bør stille dig selv: +Når du vil gemme data i din browser, er der nogle vigtige spørgsmål, du bør stille dig selv: -- *Er dataene følsomme?* Du bør undgå at gemme følsomme data på klienten, såsom brugerens adgangskoder. -- *Hvor længe har du brug for at gemme disse data?* Planlægger du kun at tilgå disse data under den aktuelle session, eller vil du have dem gemt for evigt? +- *Er dataene følsomme?* Du bør undgå at gemme følsomme data på klienten, såsom brugeradgangskoder. +- *Hvor længe har du brug for at gemme disse data?* Planlægger du at tilgå disse data kun for den aktuelle session, eller vil du have dem gemt for evigt? -Der er flere måder at gemme information i en webapp på, afhængigt af hvad du vil opnå. For eksempel kan du bruge URL'er til at gemme en søgeforespørgsel og gøre den delbar mellem brugere. Du kan også bruge [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), hvis dataene skal deles med serveren, som f.eks. [autentifikations](https://en.wikipedia.org/wiki/Authentication)-information. +Der er flere måder at gemme information i en webapp på, afhængigt af hvad du vil opnå. For eksempel kan du bruge URL'er til at gemme en søgeforespørgsel og gøre den delbar mellem brugere. Du kan også bruge [HTTP-cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), hvis dataene skal deles med serveren, såsom [autentifikations](https://en.wikipedia.org/wiki/Authentication)information. En anden mulighed er at bruge en af de mange browser-API'er til at gemme data. To af dem er særligt interessante: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), der gør det muligt at bevare data, der er specifikke for det aktuelle websted, på tværs af forskellige sessioner. De gemte data udløber aldrig. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): denne fungerer på samme måde som `localStorage`, bortset fra at de gemte data ryddes, når sessionen slutter (når browseren lukkes). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), der gør det muligt at gemme data, der er specifikke for det aktuelle websted, på tværs af forskellige sessioner. De data, der gemmes i det, udløber aldrig. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): denne fungerer på samme måde som `localStorage`, bortset fra at de data, der gemmes i det, ryddes, når sessionen afsluttes (når browseren lukkes). -Bemærk, at begge disse API'er kun tillader at gemme [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Hvis du vil gemme komplekse objekter, skal du serialisere dem til [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formatet ved hjælp af [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Bemærk, at begge disse API'er kun tillader at gemme [strenge](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Hvis du vil gemme komplekse objekter, skal du serialisere dem til [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formatet ved hjælp af [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Hvis du vil oprette en webapp, der ikke arbejder med en server, er det også muligt at oprette en database på klienten ved hjælp af [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Denne er reserveret til avancerede brugsscenarier eller hvis du har brug for at gemme betydelige mængder data, da den er mere kompleks at bruge. +✅ Hvis du vil oprette en webapp, der ikke fungerer med en server, er det også muligt at oprette en database på klienten ved hjælp af [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Denne er forbeholdt avancerede brugsscenarier eller hvis du har brug for at gemme en betydelig mængde data, da den er mere kompleks at bruge. ### Opgave -Vi vil gerne have, at vores brugere forbliver logget ind, indtil de eksplicit klikker på *Logout*-knappen, så vi bruger `localStorage` til at gemme kontodata. Først definerer vi en nøgle, som vi vil bruge til at gemme vores data. +Vi ønsker, at vores brugere forbliver logget ind, indtil de eksplicit klikker på *Log ud*-knappen, så vi vil bruge `localStorage` til at gemme kontodata. Først skal vi definere en nøgle, som vi vil bruge til at gemme vores data. ```js const storageKey = 'savedAccount'; ``` -Tilføj derefter denne linje nederst i `updateState()`-funktionen: +Tilføj derefter denne linje i slutningen af `updateState()`-funktionen: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Med dette vil brugerens kontodata blive bevaret og altid være opdateret, da vi tidligere centraliserede alle vores state-opdateringer. Det er her, vi begynder at drage fordel af alle vores tidligere refaktoreringer 🙂. +Med dette vil brugerens kontodata blive gemt og altid være opdateret, da vi tidligere centraliserede alle vores tilstandsopdateringer. Det er her, vi begynder at drage fordel af alle vores tidligere refaktoreringer 🙂. Da dataene gemmes, skal vi også tage os af at gendanne dem, når appen indlæses. Da vi begynder at have mere initialiseringskode, kan det være en god idé at oprette en ny `init`-funktion, der også inkluderer vores tidligere kode nederst i `app.js`: @@ -202,15 +202,15 @@ function init() { init(); ``` -Her henter vi de gemte data, og hvis der er nogen, opdaterer vi state tilsvarende. Det er vigtigt at gøre dette *før* opdatering af ruten, da der kan være kode, der afhænger af state under sideopdateringen. +Her henter vi de gemte data, og hvis der er nogen, opdaterer vi tilstanden i overensstemmelse hermed. Det er vigtigt at gøre dette *før* opdatering af ruten, da der kan være kode, der afhænger af tilstanden under sideopdateringen. -Vi kan også gøre *Dashboard*-siden til vores applikations standardside, da vi nu bevarer kontodata. Hvis der ikke findes data, sørger dashboardet for at omdirigere til *Login*-siden alligevel. I `updateRoute()` skal du erstatte fallback `return navigate('/login');` med `return navigate('/dashboard');`. +Vi kan også gøre *Dashboard*-siden til vores applikations standardside, da vi nu gemmer kontodataene. Hvis der ikke findes data, sørger dashboardet for at omdirigere til *Login*-siden alligevel. I `updateRoute()` skal du erstatte fallbacken `return navigate('/login');` med `return navigate('/dashboard');`. Log nu ind i appen og prøv at opdatere siden. Du bør forblive på dashboardet. Med denne opdatering har vi taget hånd om alle vores oprindelige problemer... ## Opdater dataene -...Men vi har måske også skabt et nyt problem. Ups! +...Men vi har måske også skabt et nyt. Ups! Gå til dashboardet ved hjælp af `test`-kontoen, og kør derefter denne kommando i en terminal for at oprette en ny transaktion: @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Prøv at opdatere dashboard-siden i browseren nu. Hvad sker der? Ser du den nye transaktion? +Prøv at opdatere din dashboard-side i browseren nu. Hvad sker der? Ser du den nye transaktion? -State bevares på ubestemt tid takket være `localStorage`, men det betyder også, at det aldrig opdateres, før du logger ud af appen og logger ind igen! +Tilstanden gemmes på ubestemt tid takket være `localStorage`, men det betyder også, at den aldrig opdateres, før du logger ud af appen og logger ind igen! En mulig strategi for at løse dette er at genindlæse kontodataene hver gang dashboardet indlæses, for at undgå forældede data. @@ -258,7 +258,7 @@ async function refresh() { } ``` -Denne opdaterer kontodataene og sørger derefter for at opdatere HTML'en på dashboard-siden. Det er den, vi skal kalde, når dashboard-ruten indlæses. Opdater rutedefinitionen med: +Denne opdaterer kontodataene og tager sig derefter af at opdatere HTML'en på dashboard-siden. Det er det, vi skal kalde, når dashboard-ruten indlæses. Opdater rutedefinitionen med: ```js const routes = { @@ -273,22 +273,22 @@ Prøv at genindlæse dashboardet nu, det burde vise de opdaterede kontodata. ## 🚀 Udfordring -Nu hvor vi genindlæser kontodataene hver gang dashboardet indlæses, tror du, vi stadig har brug for at bevare *alle kontodata*? +Nu hvor vi genindlæser kontodataene hver gang dashboardet indlæses, tror du, vi stadig har brug for at gemme *alle kontodata*? -Prøv at arbejde sammen om at ændre, hvad der gemmes og hentes fra `localStorage`, så det kun inkluderer det, der er absolut nødvendigt for, at appen fungerer. +Prøv at arbejde sammen om at ændre, hvad der gemmes og indlæses fra `localStorage`, så det kun inkluderer det, der er absolut nødvendigt for, at appen fungerer. ## Quiz efter forelæsning - [Quiz efter forelæsning](https://ff-quizzes.netlify.app/web/quiz/48) ## Opgave -[Implementer "Tilføj transaktion"-dialog](assignment.md) -Her er et eksempelresultat efter at have fuldført opgaven: +[Implementér dialogen "Tilføj transaktion"](assignment.md) + +Her er et eksempel på resultatet efter at have fuldført opgaven: -![Skærmbillede, der viser et eksempel på "Tilføj transaktion"-dialog](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.da.png) +![Skærmbillede, der viser et eksempel på dialogen "Tilføj transaktion"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.da.png) --- **Ansvarsfraskrivelse**: -Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på at sikre nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse. \ No newline at end of file +Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal det bemærkes, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for misforståelser eller fejltolkninger, der måtte opstå som følge af brugen af denne oversættelse. \ No newline at end of file diff --git a/translations/de/7-bank-project/4-state-management/README.md b/translations/de/7-bank-project/4-state-management/README.md index 9adc0df73..8d30dae77 100644 --- a/translations/de/7-bank-project/4-state-management/README.md +++ b/translations/de/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# Erstellen einer Banking-App Teil 4: Konzepte des State Managements +# Erstellen einer Banking-App Teil 4: Konzepte des Zustandsmanagements ## Quiz vor der Vorlesung @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Einführung -Wenn eine Webanwendung wächst, wird es zunehmend schwierig, alle Datenflüsse im Blick zu behalten. Welcher Code ruft die Daten ab, welche Seite nutzt sie, wo und wann müssen sie aktualisiert werden... Es ist leicht, am Ende mit unübersichtlichem Code dazustehen, der schwer zu warten ist. Dies gilt besonders, wenn Daten zwischen verschiedenen Seiten der App geteilt werden müssen, wie z. B. Benutzerdaten. Das Konzept des *State Managements* existiert schon immer in allen Arten von Programmen, aber da Web-Apps immer komplexer werden, ist es mittlerweile ein zentraler Punkt, über den man während der Entwicklung nachdenken muss. +Mit dem Wachstum einer Webanwendung wird es immer schwieriger, alle Datenflüsse im Blick zu behalten. Welcher Code holt die Daten, welche Seite nutzt sie, wo und wann müssen sie aktualisiert werden... Es ist leicht, unübersichtlichen Code zu erstellen, der schwer zu warten ist. Dies gilt insbesondere, wenn Daten zwischen verschiedenen Seiten der App geteilt werden müssen, wie z. B. Benutzerdaten. Das Konzept des *Zustandsmanagements* existiert schon immer in allen Arten von Programmen, aber mit der zunehmenden Komplexität von Webanwendungen ist es heute ein zentraler Punkt bei der Entwicklung. -In diesem letzten Teil werden wir die App, die wir gebaut haben, überarbeiten, um das State Management neu zu denken. Ziel ist es, die Unterstützung für Browser-Aktualisierungen zu jeder Zeit zu ermöglichen und Daten über Benutzersitzungen hinweg zu speichern. +In diesem letzten Teil werfen wir einen Blick auf die App, die wir erstellt haben, und überdenken, wie der Zustand verwaltet wird, um Unterstützung für Browseraktualisierungen zu jedem Zeitpunkt zu ermöglichen und Daten über Benutzersitzungen hinweg zu speichern. ### Voraussetzungen -Du musst den [Datenabruf](../3-data/README.md) Teil der Web-App abgeschlossen haben, um diese Lektion zu bearbeiten. Außerdem musst du [Node.js](https://nodejs.org) installieren und [den Server-API](../api/README.md) lokal ausführen, damit du Kontodaten verwalten kannst. +Du solltest den [Datenabruf](../3-data/README.md)-Teil der Web-App für diese Lektion abgeschlossen haben. Außerdem musst du [Node.js](https://nodejs.org) installieren und die [Server-API](../api/README.md) lokal ausführen, um Kontodaten zu verwalten. Du kannst testen, ob der Server ordnungsgemäß läuft, indem du diesen Befehl in einem Terminal ausführst: @@ -32,32 +32,32 @@ curl http://localhost:5000/api --- -## State Management überdenken +## Zustandsmanagement überdenken -In der [vorherigen Lektion](../3-data/README.md) haben wir ein grundlegendes Konzept des States in unserer App eingeführt, mit der globalen `account`-Variable, die die Bankdaten des aktuell angemeldeten Benutzers enthält. Unsere aktuelle Implementierung weist jedoch einige Schwächen auf. Versuche, die Seite zu aktualisieren, während du auf dem Dashboard bist. Was passiert? +In der [vorherigen Lektion](../3-data/README.md) haben wir ein grundlegendes Konzept des Zustands in unserer App eingeführt, mit der globalen Variablen `account`, die die Bankdaten des aktuell angemeldeten Benutzers enthält. Unsere aktuelle Implementierung weist jedoch einige Schwächen auf. Versuche, die Seite zu aktualisieren, während du dich auf dem Dashboard befindest. Was passiert? Es gibt drei Probleme mit dem aktuellen Code: -- Der State wird nicht gespeichert, da ein Browser-Refresh dich zurück zur Login-Seite bringt. -- Es gibt mehrere Funktionen, die den State ändern. Wenn die App wächst, kann es schwierig werden, die Änderungen nachzuverfolgen, und es ist leicht, zu vergessen, eine Aktualisierung vorzunehmen. -- Der State wird nicht bereinigt, sodass die Kontodaten noch vorhanden sind, wenn du auf *Logout* klickst, obwohl du auf der Login-Seite bist. +- Der Zustand wird nicht gespeichert, da ein Browser-Refresh dich zurück zur Login-Seite bringt. +- Es gibt mehrere Funktionen, die den Zustand ändern. Mit dem Wachstum der App wird es schwierig, die Änderungen nachzuverfolgen, und es ist leicht, das Aktualisieren einer Funktion zu vergessen. +- Der Zustand wird nicht bereinigt, sodass die Kontodaten beim Klicken auf *Logout* weiterhin vorhanden sind, obwohl du dich auf der Login-Seite befindest. Wir könnten unseren Code aktualisieren, um diese Probleme einzeln anzugehen, aber das würde zu mehr Code-Duplikation führen und die App komplexer und schwerer wartbar machen. Oder wir könnten uns ein paar Minuten Zeit nehmen und unsere Strategie überdenken. > Welche Probleme versuchen wir hier wirklich zu lösen? -[State Management](https://en.wikipedia.org/wiki/State_management) dreht sich darum, einen guten Ansatz zu finden, um diese zwei spezifischen Probleme zu lösen: +[Zustandsmanagement](https://de.wikipedia.org/wiki/State_Management) dreht sich darum, einen guten Ansatz zu finden, um diese beiden spezifischen Probleme zu lösen: -- Wie können die Datenflüsse in einer App verständlich gehalten werden? -- Wie kann der State immer mit der Benutzeroberfläche synchronisiert werden (und umgekehrt)? +- Wie kann man die Datenflüsse in einer App verständlich halten? +- Wie kann man sicherstellen, dass die Zustandsdaten immer mit der Benutzeroberfläche synchronisiert sind (und umgekehrt)? -Sobald diese Probleme gelöst sind, könnten andere Probleme entweder bereits behoben sein oder leichter zu lösen sein. Es gibt viele mögliche Ansätze, um diese Probleme zu lösen, aber wir werden eine gängige Lösung verwenden, die darin besteht, **die Daten und die Möglichkeiten, sie zu ändern, zu zentralisieren**. Die Datenflüsse würden wie folgt aussehen: +Sobald diese Probleme gelöst sind, könnten andere Probleme entweder bereits behoben sein oder leichter zu lösen sein. Es gibt viele mögliche Ansätze zur Lösung dieser Probleme, aber wir werden eine gängige Lösung verwenden, die darin besteht, **die Daten und die Möglichkeiten, sie zu ändern, zu zentralisieren**. Die Datenflüsse würden so aussehen: -![Schema, das die Datenflüsse zwischen HTML, Benutzeraktionen und State zeigt](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.de.png) +![Schema, das die Datenflüsse zwischen HTML, Benutzeraktionen und Zustand zeigt](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.de.png) -> Wir behandeln hier nicht den Teil, bei dem die Daten automatisch die Ansicht aktualisieren, da dies mit fortgeschrittenen Konzepten der [Reaktiven Programmierung](https://en.wikipedia.org/wiki/Reactive_programming) verbunden ist. Es ist ein gutes Thema für einen tiefergehenden Einstieg. +> Wir werden hier nicht den Teil behandeln, bei dem die Daten automatisch die Ansicht aktualisieren, da dies mit fortgeschritteneren Konzepten der [reaktiven Programmierung](https://de.wikipedia.org/wiki/Reaktive_Programmierung) verbunden ist. Es ist ein gutes Thema für ein tiefergehendes Studium. -✅ Es gibt viele Bibliotheken mit unterschiedlichen Ansätzen für das State Management, [Redux](https://redux.js.org) ist eine beliebte Option. Schau dir die Konzepte und Muster an, die verwendet werden, da sie oft eine gute Möglichkeit bieten, zu lernen, welche potenziellen Probleme in großen Web-Apps auftreten können und wie sie gelöst werden können. +✅ Es gibt viele Bibliotheken mit unterschiedlichen Ansätzen zum Zustandsmanagement, [Redux](https://redux.js.org) ist eine beliebte Option. Schau dir die Konzepte und Muster an, da sie oft eine gute Möglichkeit bieten, potenzielle Probleme in großen Web-Apps zu verstehen und wie sie gelöst werden können. ### Aufgabe @@ -75,9 +75,9 @@ let state = { }; ``` -Die Idee ist, *alle Daten unserer App* in einem einzigen State-Objekt zu zentralisieren. Wir haben derzeit nur `account` im State, sodass sich nicht viel ändert, aber es schafft eine Grundlage für Weiterentwicklungen. +Die Idee ist, *alle App-Daten* in einem einzigen Zustandsobjekt zu zentralisieren. Wir haben derzeit nur `account` im Zustand, daher ändert sich nicht viel, aber es schafft eine Grundlage für zukünftige Erweiterungen. -Wir müssen auch die Funktionen aktualisieren, die es verwenden. In den Funktionen `register()` und `login()` ersetze `account = ...` durch `state.account = ...`; +Wir müssen auch die Funktionen aktualisieren, die es verwenden. Ersetze in den Funktionen `register()` und `login()` `account = ...` durch `state.account = ...`; Füge am Anfang der Funktion `updateDashboard()` diese Zeile hinzu: @@ -85,13 +85,13 @@ Füge am Anfang der Funktion `updateDashboard()` diese Zeile hinzu: const account = state.account; ``` -Dieses Refactoring hat für sich genommen nicht viele Verbesserungen gebracht, aber die Idee war, die Grundlage für die nächsten Änderungen zu schaffen. +Dieses Refactoring allein bringt noch keine großen Verbesserungen, aber die Idee war, die Grundlage für die nächsten Änderungen zu schaffen. ## Datenänderungen verfolgen -Jetzt, da wir das `state`-Objekt eingerichtet haben, um unsere Daten zu speichern, ist der nächste Schritt, die Updates zu zentralisieren. Ziel ist es, Änderungen und deren Zeitpunkte leichter nachverfolgen zu können. +Nachdem wir das `state`-Objekt eingerichtet haben, um unsere Daten zu speichern, besteht der nächste Schritt darin, die Aktualisierungen zu zentralisieren. Ziel ist es, Änderungen und deren Zeitpunkt leichter nachverfolgen zu können. -Um zu vermeiden, dass Änderungen am `state`-Objekt vorgenommen werden, ist es auch eine gute Praxis, es als [*unveränderlich*](https://en.wikipedia.org/wiki/Immutable_object) zu betrachten, was bedeutet, dass es überhaupt nicht geändert werden kann. Das bedeutet auch, dass du ein neues State-Objekt erstellen musst, wenn du etwas daran ändern möchtest. Dadurch wird eine Schutzmaßnahme gegen potenziell unerwünschte [Nebenwirkungen](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) geschaffen und gleichzeitig die Möglichkeit für neue Funktionen in deiner App eröffnet, wie z. B. die Implementierung von Undo/Redo. Außerdem wird das Debuggen erleichtert. Du könntest beispielsweise jede Änderung am State protokollieren und eine Historie der Änderungen führen, um die Quelle eines Fehlers zu verstehen. +Um zu vermeiden, dass Änderungen direkt am `state`-Objekt vorgenommen werden, ist es auch eine gute Praxis, es als [*unveränderlich*](https://de.wikipedia.org/wiki/Unver%C3%A4nderliches_Objekt) zu betrachten, was bedeutet, dass es überhaupt nicht geändert werden kann. Das bedeutet auch, dass du ein neues Zustandsobjekt erstellen musst, wenn du etwas daran ändern möchtest. Auf diese Weise schützt du dich vor potenziell unerwünschten [Seiteneffekten](https://de.wikipedia.org/wiki/Seiteneffekt_(Informatik)) und eröffnest Möglichkeiten für neue Funktionen in deiner App, wie z. B. die Implementierung von Rückgängig/Wiederholen, während du gleichzeitig das Debuggen erleichterst. Zum Beispiel könntest du jede Änderung am Zustand protokollieren und eine Historie der Änderungen führen, um die Quelle eines Fehlers zu verstehen. In JavaScript kannst du [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) verwenden, um eine unveränderliche Version eines Objekts zu erstellen. Wenn du versuchst, Änderungen an einem unveränderlichen Objekt vorzunehmen, wird eine Ausnahme ausgelöst. @@ -99,7 +99,7 @@ In JavaScript kannst du [`Object.freeze()`](https://developer.mozilla.org/docs/W ### Aufgabe -Lass uns eine neue Funktion `updateState()` erstellen: +Erstelle eine neue Funktion `updateState()`: ```js function updateState(property, newData) { @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -In dieser Funktion erstellen wir ein neues State-Objekt und kopieren Daten aus dem vorherigen State mithilfe des [*Spread (`...`) Operators*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Dann überschreiben wir eine bestimmte Eigenschaft des State-Objekts mit den neuen Daten, indem wir die [Bracket-Notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` für die Zuweisung verwenden. Schließlich sperren wir das Objekt, um Änderungen zu verhindern, indem wir `Object.freeze()` verwenden. Derzeit haben wir nur die `account`-Eigenschaft im State gespeichert, aber mit diesem Ansatz kannst du so viele Eigenschaften wie nötig im State hinzufügen. +In dieser Funktion erstellen wir ein neues Zustandsobjekt und kopieren Daten aus dem vorherigen Zustand mithilfe des [*Spread-Operators (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Dann überschreiben wir eine bestimmte Eigenschaft des Zustandsobjekts mit den neuen Daten, indem wir die [Klammernotation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` für die Zuweisung verwenden. Schließlich sperren wir das Objekt, um Änderungen mit `Object.freeze()` zu verhindern. Derzeit speichern wir nur die `account`-Eigenschaft im Zustand, aber mit diesem Ansatz kannst du so viele Eigenschaften hinzufügen, wie du benötigst. -Wir aktualisieren auch die `state`-Initialisierung, um sicherzustellen, dass der anfängliche State ebenfalls eingefroren ist: +Wir aktualisieren auch die `state`-Initialisierung, um sicherzustellen, dass der Anfangszustand ebenfalls eingefroren ist: ```js let state = Object.freeze({ @@ -120,19 +120,19 @@ let state = Object.freeze({ }); ``` -Danach aktualisieren wir die Funktion `register`, indem wir die Zuweisung `state.account = result;` durch Folgendes ersetzen: +Danach aktualisiere die `register`-Funktion, indem du die Zuweisung `state.account = result;` durch Folgendes ersetzt: ```js updateState('account', result); ``` -Das Gleiche machen wir mit der Funktion `login`, indem wir `state.account = data;` durch Folgendes ersetzen: +Mache dasselbe mit der `login`-Funktion, indem du `state.account = data;` durch Folgendes ersetzt: ```js updateState('account', data); ``` -Wir nutzen die Gelegenheit, um das Problem zu beheben, dass die Kontodaten nicht gelöscht werden, wenn der Benutzer auf *Logout* klickt. +Wir nutzen die Gelegenheit, um das Problem zu beheben, dass Kontodaten nicht gelöscht werden, wenn der Benutzer auf *Logout* klickt. Erstelle eine neue Funktion `logout()`: @@ -143,35 +143,35 @@ function logout() { } ``` -Ersetze in `updateDashboard()` die Umleitung `return navigate('/login');` durch `return logout();`; +Ersetze in `updateDashboard()` die Weiterleitung `return navigate('/login');` durch `return logout();`; -Versuche, ein neues Konto zu registrieren, dich auszuloggen und erneut einzuloggen, um zu überprüfen, ob alles weiterhin korrekt funktioniert. +Versuche, ein neues Konto zu registrieren, dich abzumelden und erneut anzumelden, um zu überprüfen, ob alles noch korrekt funktioniert. -> Tipp: Du kannst dir alle State-Änderungen ansehen, indem du `console.log(state)` am Ende von `updateState()` hinzufügst und die Konsole in den Entwicklertools deines Browsers öffnest. +> Tipp: Du kannst alle Zustandsänderungen anzeigen, indem du `console.log(state)` am Ende von `updateState()` hinzufügst und die Konsole in den Entwicklerwerkzeugen deines Browsers öffnest. -## State speichern +## Zustand speichern -Die meisten Web-Apps müssen Daten speichern, um korrekt zu funktionieren. Alle kritischen Daten werden normalerweise in einer Datenbank gespeichert und über eine Server-API abgerufen, wie z. B. die Benutzerdaten in unserem Fall. Aber manchmal ist es auch interessant, einige Daten in der Client-App zu speichern, die in deinem Browser läuft, um eine bessere Benutzererfahrung oder eine verbesserte Ladeleistung zu erzielen. +Die meisten Web-Apps müssen Daten speichern, um korrekt zu funktionieren. Alle kritischen Daten werden normalerweise in einer Datenbank gespeichert und über eine Server-API abgerufen, wie z. B. die Benutzerdaten in unserem Fall. Aber manchmal ist es auch interessant, einige Daten in der Client-App zu speichern, die in deinem Browser läuft, um eine bessere Benutzererfahrung zu bieten oder die Ladeleistung zu verbessern. Wenn du Daten in deinem Browser speichern möchtest, gibt es einige wichtige Fragen, die du dir stellen solltest: - *Sind die Daten sensibel?* Du solltest vermeiden, sensible Daten wie Benutzerpasswörter auf dem Client zu speichern. -- *Wie lange möchtest du diese Daten behalten?* Planst du, auf diese Daten nur während der aktuellen Sitzung zuzugreifen, oder möchtest du sie dauerhaft speichern? +- *Wie lange möchtest du diese Daten aufbewahren?* Planst du, auf diese Daten nur während der aktuellen Sitzung zuzugreifen, oder möchtest du, dass sie dauerhaft gespeichert werden? -Es gibt verschiedene Möglichkeiten, Informationen innerhalb einer Web-App zu speichern, abhängig davon, was du erreichen möchtest. Zum Beispiel kannst du die URLs verwenden, um eine Suchanfrage zu speichern und sie zwischen Benutzern teilbar zu machen. Du kannst auch [HTTP-Cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) verwenden, wenn die Daten mit dem Server geteilt werden müssen, wie z. B. [Authentifizierungsinformationen](https://en.wikipedia.org/wiki/Authentication). +Es gibt mehrere Möglichkeiten, Informationen in einer Web-App zu speichern, je nachdem, was du erreichen möchtest. Zum Beispiel kannst du die URLs verwenden, um eine Suchanfrage zu speichern und sie zwischen Benutzern teilbar zu machen. Du kannst auch [HTTP-Cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) verwenden, wenn die Daten mit dem Server geteilt werden müssen, wie z. B. [Authentifizierungsinformationen](https://de.wikipedia.org/wiki/Authentifizierung). -Eine andere Option ist die Verwendung einer der vielen Browser-APIs zum Speichern von Daten. Zwei davon sind besonders interessant: +Eine weitere Option ist die Verwendung einer der vielen Browser-APIs zum Speichern von Daten. Zwei davon sind besonders interessant: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): ein [Key/Value Store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), der es ermöglicht, daten spezifisch für die aktuelle Website über verschiedene Sitzungen hinweg zu speichern. Die gespeicherten Daten verfallen nie. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funktioniert genauso wie `localStorage`, außer dass die darin gespeicherten Daten gelöscht werden, wenn die Sitzung endet (wenn der Browser geschlossen wird). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): Ein [Key/Value-Store](https://de.wikipedia.org/wiki/Key-Value-Datenbank), der es ermöglicht, datenbankspezifische Daten für die aktuelle Website über verschiedene Sitzungen hinweg zu speichern. Die darin gespeicherten Daten verfallen nie. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): Funktioniert genauso wie `localStorage`, außer dass die darin gespeicherten Daten gelöscht werden, wenn die Sitzung endet (wenn der Browser geschlossen wird). -Beachte, dass beide APIs nur [Strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) speichern können. Wenn du komplexe Objekte speichern möchtest, musst du sie in das [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-Format serialisieren, indem du [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) verwendest. +Beachte, dass beide APIs nur das Speichern von [Strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) erlauben. Wenn du komplexe Objekte speichern möchtest, musst du sie in das [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-Format serialisieren, indem du [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) verwendest. -✅ Wenn du eine Web-App erstellen möchtest, die nicht mit einem Server arbeitet, ist es auch möglich, eine Datenbank auf dem Client mit der [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) zu erstellen. Diese ist für fortgeschrittene Anwendungsfälle oder wenn du eine erhebliche Menge an Daten speichern musst, da sie komplexer zu verwenden ist. +✅ Wenn du eine Web-App erstellen möchtest, die ohne Server funktioniert, ist es auch möglich, eine Datenbank auf dem Client mit der [`IndexedDB`-API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) zu erstellen. Diese ist für fortgeschrittene Anwendungsfälle oder wenn du eine erhebliche Menge an Daten speichern musst, da sie komplexer zu verwenden ist. ### Aufgabe -Wir möchten, dass unsere Benutzer eingeloggt bleiben, bis sie explizit auf die *Logout*-Schaltfläche klicken. Daher verwenden wir `localStorage`, um die Kontodaten zu speichern. Zunächst definieren wir einen Schlüssel, den wir zum Speichern unserer Daten verwenden. +Wir möchten, dass unsere Benutzer angemeldet bleiben, bis sie explizit auf die Schaltfläche *Logout* klicken. Daher verwenden wir `localStorage`, um die Kontodaten zu speichern. Definiere zunächst einen Schlüssel, den wir zum Speichern unserer Daten verwenden. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ Füge dann diese Zeile am Ende der Funktion `updateState()` hinzu: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Damit werden die Benutzerdaten gespeichert und sind immer auf dem neuesten Stand, da wir zuvor alle State-Updates zentralisiert haben. Hier beginnen wir, von all unseren vorherigen Refactorings zu profitieren 🙂. +Damit werden die Benutzerdaten gespeichert und bleiben immer auf dem neuesten Stand, da wir zuvor alle Zustandsaktualisierungen zentralisiert haben. Hier beginnen wir, von all unseren vorherigen Refactorings zu profitieren 🙂. -Da die Daten gespeichert werden, müssen wir auch dafür sorgen, dass sie wiederhergestellt werden, wenn die App geladen wird. Da wir mehr Initialisierungscode haben werden, ist es eine gute Idee, eine neue Funktion `init` zu erstellen, die auch unseren vorherigen Code am Ende von `app.js` enthält: +Da die Daten gespeichert werden, müssen wir uns auch darum kümmern, sie wiederherzustellen, wenn die App geladen wird. Da wir nun mehr Initialisierungscode haben, könnte es eine gute Idee sein, eine neue Funktion `init` zu erstellen, die auch unseren bisherigen Code am Ende von `app.js` enthält: ```js function init() { @@ -202,11 +202,11 @@ function init() { init(); ``` -Hier rufen wir die gespeicherten Daten ab, und wenn welche vorhanden sind, aktualisieren wir den State entsprechend. Es ist wichtig, dies *vor* der Aktualisierung der Route zu tun, da es Code geben könnte, der während der Seitenaktualisierung auf den State angewiesen ist. +Hier rufen wir die gespeicherten Daten ab, und falls welche vorhanden sind, aktualisieren wir den Zustand entsprechend. Es ist wichtig, dies *vor* der Aktualisierung der Route zu tun, da es möglicherweise Code gibt, der während der Seitenaktualisierung auf den Zustand angewiesen ist. -Wir können auch die *Dashboard*-Seite zur Standardseite unserer Anwendung machen, da wir jetzt die Kontodaten speichern. Wenn keine Daten gefunden werden, kümmert sich das Dashboard ohnehin darum, zur *Login*-Seite umzuleiten. Ersetze in `updateRoute()` den Fallback `return navigate('/login');` durch `return navigate('/dashboard');`. +Wir können auch die *Dashboard*-Seite zur Standardseite unserer Anwendung machen, da wir jetzt die Kontodaten speichern. Wenn keine Daten gefunden werden, kümmert sich das Dashboard ohnehin um die Weiterleitung zur *Login*-Seite. Ersetze in `updateRoute()` den Fallback `return navigate('/login');` durch `return navigate('/dashboard');`. -Logge dich jetzt in die App ein und versuche, die Seite zu aktualisieren. Du solltest auf dem Dashboard bleiben. Mit diesem Update haben wir alle unsere anfänglichen Probleme gelöst... +Melde dich jetzt in der App an und versuche, die Seite zu aktualisieren. Du solltest auf dem Dashboard bleiben. Mit diesem Update haben wir alle unsere anfänglichen Probleme gelöst... ## Daten aktualisieren @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Versuche jetzt, die Dashboard-Seite im Browser zu aktualisieren. Was passiert? Siehst du die neue Transaktion? +Versuche jetzt, die Dashboard-Seite in deinem Browser zu aktualisieren. Was passiert? Siehst du die neue Transaktion? -Der State wird dank `localStorage` unbegrenzt gespeichert, aber das bedeutet auch, dass er nie aktualisiert wird, bis du dich aus der App ausloggst und wieder einloggst! +Der Zustand wird dank `localStorage` unbegrenzt gespeichert, aber das bedeutet auch, dass er nie aktualisiert wird, bis du dich aus der App abmeldest und wieder anmeldest! -Eine mögliche Strategie, um das zu beheben, ist, die Kontodaten jedes Mal neu zu laden, wenn das Dashboard geladen wird, um veraltete Daten zu vermeiden. +Eine mögliche Strategie, um das zu beheben, besteht darin, die Kontodaten jedes Mal neu zu laden, wenn das Dashboard geladen wird, um veraltete Daten zu vermeiden. ### Aufgabe @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Diese Methode überprüft, ob wir derzeit eingeloggt sind, und lädt dann die Kontodaten vom Server neu. +Diese Methode überprüft, ob wir derzeit angemeldet sind, und lädt dann die Kontodaten vom Server neu. Erstelle eine weitere Funktion namens `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Diese Funktion aktualisiert die Kontodaten und kümmert sich dann um die Aktualisierung des HTML des Dashboard-Seite. Sie ist das, was wir aufrufen müssen, wenn die Dashboard-Route geladen wird. Aktualisiere die Routen-Definition mit: +Diese Funktion aktualisiert die Kontodaten und kümmert sich dann um die Aktualisierung des HTMLs der Dashboard-Seite. Sie ist das, was wir aufrufen müssen, wenn die Dashboard-Route geladen wird. Aktualisiere die Routendefinition mit: ```js const routes = { @@ -273,22 +273,22 @@ Versuche jetzt, das Dashboard zu aktualisieren. Es sollte die aktualisierten Kon ## 🚀 Herausforderung -Da wir die Kontodaten jedes Mal neu laden, wenn das Dashboard geladen wird, denkst du, dass wir immer noch *alle Kontodaten* speichern müssen? +Da wir die Kontodaten jedes Mal neu laden, wenn das Dashboard geladen wird, denkst du, dass wir *alle Kontodaten* weiterhin speichern müssen? -Versuche gemeinsam zu arbeiten, um zu ändern, was in `localStorage` gespeichert und geladen wird, sodass nur das gespeichert wird, was absolut notwendig ist, damit die App funktioniert. +Versuche gemeinsam zu erarbeiten, was minimal in `localStorage` gespeichert und geladen werden muss, damit die App funktioniert. ## Quiz nach der Vorlesung - [Quiz nach der Vorlesung](https://ff-quizzes.netlify.app/web/quiz/48) ## Aufgabe -[Implementieren Sie den Dialog "Transaktion hinzufügen"](assignment.md) + +[Dialog "Transaktion hinzufügen" implementieren](assignment.md) Hier ist ein Beispielergebnis nach Abschluss der Aufgabe: -![Screenshot, der ein Beispiel für den Dialog "Transaktion hinzufügen" zeigt](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.de.png) +![Screenshot, der einen Beispiel-Dialog "Transaktion hinzufügen" zeigt](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.de.png) --- **Haftungsausschluss**: -Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, beachten Sie bitte, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben. \ No newline at end of file +Dieses Dokument wurde mit dem KI-Übersetzungsdienst [Co-op Translator](https://github.com/Azure/co-op-translator) übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die sich aus der Nutzung dieser Übersetzung ergeben. \ No newline at end of file diff --git a/translations/el/7-bank-project/4-state-management/README.md b/translations/el/7-bank-project/4-state-management/README.md index de10c8352..591a32ee8 100644 --- a/translations/el/7-bank-project/4-state-management/README.md +++ b/translations/el/7-bank-project/4-state-management/README.md @@ -1,29 +1,29 @@ # Δημιουργία Εφαρμογής Τραπεζικής Μέρος 4: Έννοιες Διαχείρισης Κατάστασης -## Ερωτηματολόγιο Πριν το Μάθημα +## Κουίζ Πριν το Μάθημα -[Ερωτηματολόγιο πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/47) +[Κουίζ πριν το μάθημα](https://ff-quizzes.netlify.app/web/quiz/47) ### Εισαγωγή -Καθώς μια διαδικτυακή εφαρμογή μεγαλώνει, γίνεται πρόκληση να παρακολουθείς όλες τις ροές δεδομένων. Ποιος κώδικας λαμβάνει τα δεδομένα, ποια σελίδα τα χρησιμοποιεί, πού και πότε πρέπει να ενημερωθούν... είναι εύκολο να καταλήξεις με ακατάστατο κώδικα που είναι δύσκολο να συντηρηθεί. Αυτό ισχύει ιδιαίτερα όταν χρειάζεται να μοιραστείς δεδομένα μεταξύ διαφορετικών σελίδων της εφαρμογής σου, όπως τα δεδομένα χρήστη. Η έννοια της *διαχείρισης κατάστασης* υπήρχε πάντα σε κάθε είδους προγράμματα, αλλά καθώς οι διαδικτυακές εφαρμογές γίνονται όλο και πιο περίπλοκες, είναι πλέον ένα βασικό σημείο που πρέπει να λαμβάνεται υπόψη κατά την ανάπτυξη. +Καθώς μια διαδικτυακή εφαρμογή μεγαλώνει, γίνεται πρόκληση να παρακολουθείς όλες τις ροές δεδομένων. Ποιος κώδικας λαμβάνει τα δεδομένα, ποια σελίδα τα χρησιμοποιεί, πού και πότε πρέπει να ενημερωθούν... είναι εύκολο να καταλήξεις με μπερδεμένο κώδικα που είναι δύσκολο να συντηρηθεί. Αυτό ισχύει ιδιαίτερα όταν χρειάζεται να μοιραστείς δεδομένα μεταξύ διαφορετικών σελίδων της εφαρμογής σου, όπως τα δεδομένα χρήστη. Η έννοια της *διαχείρισης κατάστασης* υπήρχε πάντα σε κάθε είδους προγράμματα, αλλά καθώς οι διαδικτυακές εφαρμογές γίνονται όλο και πιο περίπλοκες, είναι πλέον ένα βασικό σημείο που πρέπει να λαμβάνεται υπόψη κατά την ανάπτυξη. -Σε αυτό το τελευταίο μέρος, θα εξετάσουμε την εφαρμογή που δημιουργήσαμε για να επανεξετάσουμε πώς διαχειρίζεται η κατάσταση, επιτρέποντας την υποστήριξη ανανέωσης του προγράμματος περιήγησης οποιαδήποτε στιγμή και τη διατήρηση δεδομένων μεταξύ των συνεδριών χρήστη. +Σε αυτό το τελευταίο μέρος, θα επανεξετάσουμε την εφαρμογή που δημιουργήσαμε για να αναθεωρήσουμε πώς διαχειρίζεται η κατάσταση, επιτρέποντας την υποστήριξη ανανέωσης του προγράμματος περιήγησης οποιαδήποτε στιγμή και τη διατήρηση δεδομένων μεταξύ των συνεδριών χρήστη. ### Προαπαιτούμενα -Πρέπει να έχεις ολοκληρώσει το μέρος [ανάκτησης δεδομένων](../3-data/README.md) της διαδικτυακής εφαρμογής για αυτό το μάθημα. Πρέπει επίσης να εγκαταστήσεις το [Node.js](https://nodejs.org) και να [εκτελέσεις το API του διακομιστή](../api/README.md) τοπικά ώστε να μπορείς να διαχειριστείς τα δεδομένα λογαριασμού. +Πρέπει να έχεις ολοκληρώσει το μέρος [ανάκτησης δεδομένων](../3-data/README.md) της διαδικτυακής εφαρμογής για αυτό το μάθημα. Πρέπει επίσης να εγκαταστήσεις το [Node.js](https://nodejs.org) και να [εκτελέσεις το API διακομιστή](../api/README.md) τοπικά ώστε να μπορείς να διαχειριστείς τα δεδομένα λογαριασμού. -Μπορείς να δοκιμάσεις ότι ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό: +Μπορείς να ελέγξεις ότι ο διακομιστής λειτουργεί σωστά εκτελώντας αυτήν την εντολή σε ένα τερματικό: ```sh curl http://localhost:5000/api @@ -32,26 +32,26 @@ curl http://localhost:5000/api --- -## Επανεξέταση της διαχείρισης κατάστασης +## Αναθεώρηση της διαχείρισης κατάστασης Στο [προηγούμενο μάθημα](../3-data/README.md), εισαγάγαμε μια βασική έννοια κατάστασης στην εφαρμογή μας με τη χρήση της παγκόσμιας μεταβλητής `account`, η οποία περιέχει τα τραπεζικά δεδομένα του χρήστη που είναι συνδεδεμένος. Ωστόσο, η τρέχουσα υλοποίησή μας έχει κάποια προβλήματα. Δοκίμασε να ανανεώσεις τη σελίδα όταν βρίσκεσαι στον πίνακα ελέγχου. Τι συμβαίνει; Υπάρχουν 3 προβλήματα με τον τρέχοντα κώδικα: -- Η κατάσταση δεν διατηρείται, καθώς η ανανέωση του προγράμματος περιήγησης σε επιστρέφει στη σελίδα σύνδεσης. -- Υπάρχουν πολλές συναρτήσεις που τροποποιούν την κατάσταση. Καθώς η εφαρμογή μεγαλώνει, μπορεί να γίνει δύσκολο να παρακολουθήσεις τις αλλαγές και είναι εύκολο να ξεχάσεις να ενημερώσεις μία. -- Η κατάσταση δεν καθαρίζεται, οπότε όταν κάνεις κλικ στο *Αποσύνδεση*, τα δεδομένα του λογαριασμού παραμένουν εκεί, παρόλο που βρίσκεσαι στη σελίδα σύνδεσης. +- Η κατάσταση δεν διατηρείται, καθώς μια ανανέωση του προγράμματος περιήγησης σε επιστρέφει στη σελίδα σύνδεσης. +- Υπάρχουν πολλές συναρτήσεις που τροποποιούν την κατάσταση. Καθώς η εφαρμογή μεγαλώνει, αυτό μπορεί να δυσκολέψει την παρακολούθηση των αλλαγών και είναι εύκολο να ξεχάσεις να ενημερώσεις κάτι. +- Η κατάσταση δεν καθαρίζεται, οπότε όταν κάνεις κλικ στο *Αποσύνδεση*, τα δεδομένα του λογαριασμού παραμένουν, παρόλο που βρίσκεσαι στη σελίδα σύνδεσης. -Θα μπορούσαμε να ενημερώσουμε τον κώδικα μας για να αντιμετωπίσουμε αυτά τα προβλήματα ένα προς ένα, αλλά αυτό θα δημιουργούσε περισσότερη επανάληψη κώδικα και θα έκανε την εφαρμογή πιο περίπλοκη και δύσκολη στη συντήρηση. Ή θα μπορούσαμε να σταματήσουμε για λίγα λεπτά και να επανεξετάσουμε τη στρατηγική μας. +Θα μπορούσαμε να ενημερώσουμε τον κώδικά μας για να αντιμετωπίσουμε αυτά τα προβλήματα ένα προς ένα, αλλά αυτό θα δημιουργούσε περισσότερη επανάληψη κώδικα και θα έκανε την εφαρμογή πιο περίπλοκη και δύσκολη στη συντήρηση. Ή θα μπορούσαμε να σταματήσουμε για λίγα λεπτά και να αναθεωρήσουμε τη στρατηγική μας. > Ποια προβλήματα προσπαθούμε πραγματικά να λύσουμε εδώ; Η [διαχείριση κατάστασης](https://en.wikipedia.org/wiki/State_management) αφορά την εύρεση μιας καλής προσέγγισης για την επίλυση αυτών των δύο συγκεκριμένων προβλημάτων: - Πώς να διατηρήσουμε τις ροές δεδομένων σε μια εφαρμογή κατανοητές; -- Πώς να διατηρήσουμε τα δεδομένα κατάστασης πάντα συγχρονισμένα με τη διεπαφή χρήστη (και αντίστροφα); +- Πώς να διατηρήσουμε τα δεδομένα κατάστασης πάντα συγχρονισμένα με τη διεπαφή χρήστη (και το αντίστροφο); -Μόλις φροντίσεις αυτά τα ζητήματα, οποιαδήποτε άλλα προβλήματα μπορεί να έχεις είτε θα έχουν ήδη λυθεί είτε θα έχουν γίνει ευκολότερα να λυθούν. Υπάρχουν πολλές πιθανές προσεγγίσεις για την επίλυση αυτών των προβλημάτων, αλλά θα ακολουθήσουμε μια κοινή λύση που συνίσταται στο **να κεντροποιήσουμε τα δεδομένα και τους τρόπους αλλαγής τους**. Οι ροές δεδομένων θα λειτουργούν ως εξής: +Αφού αντιμετωπίσεις αυτά τα ζητήματα, οποιαδήποτε άλλα προβλήματα μπορεί να έχουν ήδη λυθεί ή να έχουν γίνει ευκολότερα να λυθούν. Υπάρχουν πολλές πιθανές προσεγγίσεις για την επίλυση αυτών των προβλημάτων, αλλά θα ακολουθήσουμε μια κοινή λύση που συνίσταται στο **να κεντροποιήσουμε τα δεδομένα και τους τρόπους αλλαγής τους**. Οι ροές δεδομένων θα λειτουργούν ως εξής: ![Σχήμα που δείχνει τις ροές δεδομένων μεταξύ του HTML, των ενεργειών χρήστη και της κατάστασης](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.el.png) @@ -75,9 +75,9 @@ let state = { }; ``` -Η ιδέα είναι να *κεντροποιήσουμε* όλα τα δεδομένα της εφαρμογής μας σε ένα μόνο αντικείμενο κατάστασης. Προς το παρόν έχουμε μόνο το `account` στην κατάσταση, οπότε δεν αλλάζει πολύ, αλλά δημιουργεί μια βάση για μελλοντικές εξελίξεις. +Η ιδέα είναι να *κεντροποιήσουμε* όλα τα δεδομένα της εφαρμογής μας σε ένα μόνο αντικείμενο κατάστασης. Προς το παρόν έχουμε μόνο το `account` στην κατάσταση, οπότε δεν αλλάζει πολλά, αλλά δημιουργεί μια βάση για μελλοντικές εξελίξεις. -Πρέπει επίσης να ενημερώσουμε τις συναρτήσεις που το χρησιμοποιούν. Στις συναρτήσεις `register()` και `login()`, αντικατάστησε το `account = ...` με `state.account = ...`; +Πρέπει επίσης να ενημερώσουμε τις συναρτήσεις που το χρησιμοποιούν. Στις συναρτήσεις `register()` και `login()`, αντικατάστησε το `account = ...` με `state.account = ...`. Στην αρχή της συνάρτησης `updateDashboard()`, πρόσθεσε αυτή τη γραμμή: @@ -89,9 +89,9 @@ const account = state.account; ## Παρακολούθηση αλλαγών δεδομένων -Τώρα που έχουμε θέσει το αντικείμενο `state` για την αποθήκευση των δεδομένων μας, το επόμενο βήμα είναι να κεντροποιήσουμε τις ενημερώσεις. Στόχος είναι να γίνει ευκολότερο να παρακολουθούμε οποιεσδήποτε αλλαγές και πότε συμβαίνουν. +Τώρα που έχουμε θέσει το αντικείμενο `state` για την αποθήκευση των δεδομένων μας, το επόμενο βήμα είναι να κεντροποιήσουμε τις ενημερώσεις. Στόχος είναι να γίνει ευκολότερη η παρακολούθηση οποιωνδήποτε αλλαγών και πότε αυτές συμβαίνουν. -Για να αποφύγουμε την πραγματοποίηση αλλαγών στο αντικείμενο `state`, είναι επίσης καλή πρακτική να το θεωρούμε [*αμετάβλητο*](https://en.wikipedia.org/wiki/Immutable_object), που σημαίνει ότι δεν μπορεί να τροποποιηθεί καθόλου. Αυτό σημαίνει επίσης ότι πρέπει να δημιουργήσεις ένα νέο αντικείμενο κατάστασης αν θέλεις να αλλάξεις κάτι σε αυτό. Με αυτόν τον τρόπο, δημιουργείς προστασία από πιθανές ανεπιθύμητες [παρενέργειες](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) και ανοίγεις δυνατότητες για νέες λειτουργίες στην εφαρμογή σου, όπως η υλοποίηση undo/redo, ενώ ταυτόχρονα διευκολύνεις την αποσφαλμάτωση. Για παράδειγμα, θα μπορούσες να καταγράψεις κάθε αλλαγή που γίνεται στην κατάσταση και να διατηρήσεις ένα ιστορικό των αλλαγών για να κατανοήσεις την πηγή ενός σφάλματος. +Για να αποφύγουμε αλλαγές στο αντικείμενο `state`, είναι επίσης καλή πρακτική να το θεωρούμε [*αμετάβλητο*](https://en.wikipedia.org/wiki/Immutable_object), που σημαίνει ότι δεν μπορεί να τροποποιηθεί καθόλου. Αυτό σημαίνει επίσης ότι πρέπει να δημιουργήσεις ένα νέο αντικείμενο κατάστασης αν θέλεις να αλλάξεις κάτι σε αυτό. Με αυτόν τον τρόπο, δημιουργείς μια προστασία από πιθανές ανεπιθύμητες [παρενέργειες](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) και ανοίγεις δυνατότητες για νέες λειτουργίες στην εφαρμογή σου, όπως η υλοποίηση αναίρεσης/επανάληψης, ενώ ταυτόχρονα διευκολύνεις την αποσφαλμάτωση. Για παράδειγμα, θα μπορούσες να καταγράψεις κάθε αλλαγή που γίνεται στην κατάσταση και να διατηρήσεις ένα ιστορικό των αλλαγών για να κατανοήσεις την πηγή ενός σφάλματος. Στην JavaScript, μπορείς να χρησιμοποιήσεις το [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) για να δημιουργήσεις μια αμετάβλητη έκδοση ενός αντικειμένου. Αν προσπαθήσεις να κάνεις αλλαγές σε ένα αμετάβλητο αντικείμενο, θα προκληθεί εξαίρεση. @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -Σε αυτή τη συνάρτηση, δημιουργούμε ένα νέο αντικείμενο κατάστασης και αντιγράφουμε δεδομένα από την προηγούμενη κατάσταση χρησιμοποιώντας τον [*τελεστή spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Στη συνέχεια, αντικαθιστούμε μια συγκεκριμένη ιδιότητα του αντικειμένου κατάστασης με τα νέα δεδομένα χρησιμοποιώντας τη [σημειογραφία αγκύλης](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` για την ανάθεση. Τέλος, κλειδώνουμε το αντικείμενο για να αποτρέψουμε τροποποιήσεις χρησιμοποιώντας το `Object.freeze()`. Προς το παρόν, έχουμε μόνο την ιδιότητα `account` αποθηκευμένη στην κατάσταση, αλλά με αυτήν την προσέγγιση μπορείς να προσθέσεις όσες ιδιότητες χρειάζεσαι στην κατάσταση. +Σε αυτή τη συνάρτηση, δημιουργούμε ένα νέο αντικείμενο κατάστασης και αντιγράφουμε δεδομένα από την προηγούμενη κατάσταση χρησιμοποιώντας τον [*τελεστή εξάπλωσης (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Στη συνέχεια, αντικαθιστούμε μια συγκεκριμένη ιδιότητα του αντικειμένου κατάστασης με τα νέα δεδομένα χρησιμοποιώντας τη [σημειογραφία αγκύλης](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` για την ανάθεση. Τέλος, κλειδώνουμε το αντικείμενο για να αποτρέψουμε τροποποιήσεις χρησιμοποιώντας το `Object.freeze()`. Προς το παρόν, έχουμε μόνο την ιδιότητα `account` αποθηκευμένη στην κατάσταση, αλλά με αυτή την προσέγγιση μπορείς να προσθέσεις όσες ιδιότητες χρειάζεσαι. -Θα ενημερώσουμε επίσης την αρχικοποίηση της `state` για να βεβαιωθούμε ότι η αρχική κατάσταση είναι επίσης κλειδωμένη: +Θα ενημερώσουμε επίσης την αρχικοποίηση του `state` για να διασφαλίσουμε ότι η αρχική κατάσταση είναι επίσης κλειδωμένη: ```js let state = Object.freeze({ @@ -132,7 +132,7 @@ updateState('account', result); updateState('account', data); ``` -Τώρα θα εκμεταλλευτούμε την ευκαιρία να διορθώσουμε το πρόβλημα των δεδομένων λογαριασμού που δεν καθαρίζονται όταν ο χρήστης κάνει κλικ στο *Αποσύνδεση*. +Τώρα θα εκμεταλλευτούμε την ευκαιρία να διορθώσουμε το πρόβλημα των δεδομένων λογαριασμού που δεν διαγράφονται όταν ο χρήστης κάνει κλικ στο *Αποσύνδεση*. Δημιούργησε μια νέα συνάρτηση `logout()`: @@ -143,29 +143,29 @@ function logout() { } ``` -Στην `updateDashboard()`, αντικατάστησε την ανακατεύθυνση `return navigate('/login');` με `return logout();` +Στη συνάρτηση `updateDashboard()`, αντικατάστησε την ανακατεύθυνση `return navigate('/login');` με `return logout();`. -Δοκίμασε να εγγραφείς σε έναν νέο λογαριασμό, να αποσυνδεθείς και να συνδεθείς ξανά για να ελέγξεις ότι όλα λειτουργούν σωστά. +Δοκίμασε να εγγραφείς με νέο λογαριασμό, να αποσυνδεθείς και να συνδεθείς ξανά για να ελέγξεις ότι όλα λειτουργούν σωστά. > Συμβουλή: μπορείς να δεις όλες τις αλλαγές κατάστασης προσθέτοντας `console.log(state)` στο τέλος της `updateState()` και ανοίγοντας την κονσόλα στα εργαλεία ανάπτυξης του προγράμματος περιήγησης. ## Διατήρηση της κατάστασης -Οι περισσότερες διαδικτυακές εφαρμογές χρειάζονται να διατηρούν δεδομένα για να λειτουργούν σωστά. Όλα τα κρίσιμα δεδομένα συνήθως αποθηκεύονται σε μια βάση δεδομένων και προσπελάζονται μέσω ενός API διακομιστή, όπως τα δεδομένα λογαριασμού χρήστη στην περίπτωσή μας. Αλλά μερικές φορές, είναι επίσης ενδιαφέρον να διατηρείς κάποια δεδομένα στην εφαρμογή πελάτη που εκτελείται στο πρόγραμμα περιήγησης, για καλύτερη εμπειρία χρήστη ή για βελτίωση της απόδοσης φόρτωσης. +Οι περισσότερες διαδικτυακές εφαρμογές χρειάζονται να διατηρούν δεδομένα για να λειτουργούν σωστά. Όλα τα κρίσιμα δεδομένα συνήθως αποθηκεύονται σε μια βάση δεδομένων και είναι προσβάσιμα μέσω ενός API διακομιστή, όπως τα δεδομένα λογαριασμού χρήστη στην περίπτωσή μας. Αλλά μερικές φορές, είναι επίσης ενδιαφέρον να διατηρείς κάποια δεδομένα στην εφαρμογή πελάτη που εκτελείται στο πρόγραμμα περιήγησης, για καλύτερη εμπειρία χρήστη ή για βελτίωση της απόδοσης φόρτωσης. Όταν θέλεις να διατηρήσεις δεδομένα στο πρόγραμμα περιήγησης, υπάρχουν μερικές σημαντικές ερωτήσεις που πρέπει να κάνεις: -- *Είναι τα δεδομένα ευαίσθητα;* Θα πρέπει να αποφεύγεις την αποθήκευση οποιωνδήποτε ευαίσθητων δεδομένων στον πελάτη, όπως κωδικούς πρόσβασης χρηστών. -- *Για πόσο καιρό χρειάζεσαι να διατηρήσεις αυτά τα δεδομένα;* Σκοπεύεις να προσπελάσεις αυτά τα δεδομένα μόνο για την τρέχουσα συνεδρία ή θέλεις να αποθηκευτούν για πάντα; +- *Είναι τα δεδομένα ευαίσθητα;* Πρέπει να αποφεύγεις την αποθήκευση οποιωνδήποτε ευαίσθητων δεδομένων στον πελάτη, όπως κωδικούς πρόσβασης χρηστών. +- *Για πόσο καιρό χρειάζεσαι να διατηρήσεις αυτά τα δεδομένα;* Σκοπεύεις να έχεις πρόσβαση σε αυτά τα δεδομένα μόνο για την τρέχουσα συνεδρία ή θέλεις να αποθηκευτούν για πάντα; Υπάρχουν πολλοί τρόποι αποθήκευσης πληροφοριών μέσα σε μια διαδικτυακή εφαρμογή, ανάλογα με το τι θέλεις να επιτύχεις. Για παράδειγμα, μπορείς να χρησιμοποιήσεις τις διευθύνσεις URL για να αποθηκεύσεις ένα ερώτημα αναζήτησης και να το κάνεις κοινόχρηστο μεταξύ χρηστών. Μπορείς επίσης να χρησιμοποιήσεις [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) αν τα δεδομένα χρειάζεται να μοιραστούν με τον διακομιστή, όπως πληροφορίες [αυθεντικοποίησης](https://en.wikipedia.org/wiki/Authentication). Μια άλλη επιλογή είναι να χρησιμοποιήσεις μία από τις πολλές APIs του προγράμματος περιήγησης για την αποθήκευση δεδομένων. Δύο από αυτές είναι ιδιαίτερα ενδιαφέρουσες: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): ένα [Κατάστημα Κλειδιού/Τιμής](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) που επιτρέπει τη διατήρηση δεδομένων συγκεκριμένων για την τρέχουσα ιστοσελίδα μεταξύ διαφορετικών συνεδριών. Τα δεδομένα που αποθηκεύονται σε αυτό δεν λήγουν ποτέ. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): αυτό λειτουργεί το ίδιο με το `localStorage` εκτός από το ότι τα δεδομένα που αποθηκεύονται σε αυτό διαγράφονται όταν η συνεδρία τελειώσει (όταν κλείσει το πρόγραμμα περιήγησης). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): ένα [Κατάστημα Κλειδιού/Τιμής](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) που επιτρέπει τη διατήρηση δεδομένων συγκεκριμένων για τον τρέχοντα ιστότοπο μεταξύ διαφορετικών συνεδριών. Τα δεδομένα που αποθηκεύονται σε αυτό δεν λήγουν ποτέ. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): λειτουργεί το ίδιο με το `localStorage`, εκτός από το ότι τα δεδομένα που αποθηκεύονται σε αυτό διαγράφονται όταν τελειώνει η συνεδρία (όταν κλείνει το πρόγραμμα περιήγησης). -Σημείωσε ότι και οι δύο αυτές APIs επιτρέπουν μόνο την αποθήκευση [συμβολοσειρών](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Αν θέλεις να αποθηκεύσεις σύνθετα αντικείμενα, θα χρειαστεί να τα σειριοποιήσεις στη μορφή [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) χρησιμοποιώντας το [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Σημείωσε ότι και οι δύο αυτές APIs επιτρέπουν μόνο την αποθήκευση [συμβολοσειρών](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Αν θέλεις να αποθηκεύσεις σύνθετα αντικείμενα, θα χρειαστεί να τα μετατρέψεις σε μορφή [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) χρησιμοποιώντας το [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). ✅ Αν θέλεις να δημιουργήσεις μια διαδικτυακή εφαρμογή που δεν λειτουργεί με διακομιστή, είναι επίσης δυνατό να δημιουργήσεις μια βάση δεδομένων στον πελάτη χρησιμοποιώντας το [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Αυτό προορίζεται για προχωρημένες περιπτώσεις χρήσης ή αν χρειάζεσαι να αποθηκεύσεις σημαντική ποσότητα δεδομένων, καθώς είναι πιο περίπλοκο στη χρήση. @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Με αυτό, τα δεδομένα λογαριασμού χρήστη θα διατηρούνται και θα είναι πάντα ενημερωμένα καθώς κεντροποιήσαμε προηγουμένως όλες τις ενημερώσεις κατάστασης. Εδώ αρχίζουμε να επωφελούμαστε από όλες τις προηγούμενες αναδιαρθρώσεις μας 🙂. +Με αυτό, τα δεδομένα λογαριασμού χρήστη θα διατηρούνται και θα είναι πάντα ενημερωμένα, καθώς προηγουμένως κεντροποιήσαμε όλες τις ενημερώσεις κατάστασης. Εδώ αρχίζουμε να επωφελούμαστε από όλες τις προηγούμενες αναδιαρθρώσεις μας 🙂. -Καθώς τα δεδομένα αποθηκεύονται, πρέπει επίσης να φροντίσουμε να τα επαναφέρουμε όταν φορτώνεται η εφαρμογή. Επειδή θα αρχίσουμε να έχουμε περισσότερο κώδικα αρχικοποίησης, μπορεί να είναι καλή ιδέα να δημιουργήσουμε μια νέα συνάρτηση `init`, που περιλαμβάνει επίσης τον προηγούμενο κώδικα στο κάτω μέρος του `app.js`: +Καθώς τα δεδομένα αποθηκεύονται, πρέπει επίσης να φροντίσουμε για την επαναφορά τους όταν φορτώνεται η εφαρμογή. Δεδομένου ότι θα αρχίσουμε να έχουμε περισσότερο κώδικα αρχικοποίησης, μπορεί να είναι καλή ιδέα να δημιουργήσουμε μια νέα συνάρτηση `init`, η οποία θα περιλαμβάνει και τον προηγούμενο κώδικα στο τέλος του `app.js`: ```js function init() { @@ -202,16 +202,20 @@ function init() { init(); ``` -Εδώ ανακτούμε τα αποθηκευμένα δεδομένα και, αν υπάρχουν, ενημερώνουμε την κατάσταση ανάλογα. Είναι σημαντικό να το κάνουμε *πριν* ενημερώσουμε τη διαδρομή, καθώς μπορεί να υπάρχει κώδικας που βασίζεται στην κατάσταση κατά την ενημέρωση της σελίδας. +Εδώ ανακτούμε τα αποθηκευμένα δεδομένα και, αν υπάρχουν, ενημερώνουμε την κατάσταση ανάλογα. Είναι σημαντικό να το κάνουμε αυτό *πριν* ενημερώσουμε τη διαδρομή, καθώς μπορεί να υπάρχει κώδικας που βασίζεται στην κατάσταση κατά την ενημέρωση της σελίδας. -Μπορούμε επίσης να κάνουμε τη σελίδα *Πίνακας Ελέγχου* την προεπιλεγμένη σελίδα της εφαρμογής μας, καθώς τώρα διατηρούμε τα δεδομένα λογαριασμού. Αν δεν βρεθούν δεδομένα, ο πίνακας ελέγχου φροντίζει να ανακατευθύνει στη σελίδα *Σύνδεση* ούτως ή άλλως. Στην `updateRoute()`, αντικατάστησε την εναλλακτική `return navigate('/login');` με `return navigate('/dashboard -[Υλοποίηση του διαλόγου "Προσθήκη συναλλαγής"](assignment.md) +Μπορούμε επίσης να κάνουμε τη σελίδα *Πίνακας Ελέγχου* την προεπιλεγμένη σελίδα της εφαρμογής μας, καθώς τώρα διατηρούμε τα δεδομένα λογαριασμού. Αν δεν βρεθούν δεδομένα, ο πίνακας ελέγχου φροντίζει να ανακατευθύνει στη σελίδα *Σύνδεση* ούτως ή άλλως. Στη συνάρτηση `updateRoute()`, αντικατάστησε την προεπιλεγμένη `return navigate('/login');` με ` +[Κουίζ μετά τη διάλεξη](https://ff-quizzes.netlify.app/web/quiz/48) + +## Εργασία + +[Υλοποιήστε το παράθυρο διαλόγου "Προσθήκη συναλλαγής"](assignment.md) Ακολουθεί ένα παράδειγμα αποτελέσματος μετά την ολοκλήρωση της εργασίας: -![Στιγμιότυπο που δείχνει ένα παράδειγμα διαλόγου "Προσθήκη συναλλαγής"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.el.png) +![Στιγμιότυπο που δείχνει ένα παράδειγμα παραθύρου διαλόγου "Προσθήκη συναλλαγής"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.el.png) --- -**Αποποίηση Ευθύνης**: -Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης AI [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε κάθε προσπάθεια για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν λάθη ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης. \ No newline at end of file +**Αποποίηση ευθύνης**: +Αυτό το έγγραφο έχει μεταφραστεί χρησιμοποιώντας την υπηρεσία αυτόματης μετάφρασης [Co-op Translator](https://github.com/Azure/co-op-translator). Παρόλο που καταβάλλουμε προσπάθειες για ακρίβεια, παρακαλούμε να έχετε υπόψη ότι οι αυτόματες μεταφράσεις ενδέχεται να περιέχουν σφάλματα ή ανακρίβειες. Το πρωτότυπο έγγραφο στη μητρική του γλώσσα θα πρέπει να θεωρείται η αυθεντική πηγή. Για κρίσιμες πληροφορίες, συνιστάται επαγγελματική ανθρώπινη μετάφραση. Δεν φέρουμε ευθύνη για τυχόν παρεξηγήσεις ή εσφαλμένες ερμηνείες που προκύπτουν από τη χρήση αυτής της μετάφρασης. \ No newline at end of file diff --git a/translations/en/7-bank-project/4-state-management/README.md b/translations/en/7-bank-project/4-state-management/README.md index 875363879..6a8348acf 100644 --- a/translations/en/7-bank-project/4-state-management/README.md +++ b/translations/en/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# ساخت یک اپلیکیشن بانکی بخش ۴: مفاهیم مدیریت وضعیت +# ساخت اپلیکیشن بانکی قسمت ۴: مفاهیم مدیریت وضعیت ## آزمون پیش از درس @@ -15,15 +15,15 @@ CO_OP_TRANSLATOR_METADATA: ### مقدمه -با رشد یک اپلیکیشن وب، پیگیری جریان‌های داده به یک چالش تبدیل می‌شود. کدام کد داده‌ها را دریافت می‌کند، کدام صفحه از آن استفاده می‌کند، کجا و چه زمانی باید به‌روزرسانی شود... به‌راحتی می‌توان به کدی شلوغ و دشوار برای نگهداری رسید. این موضوع به‌ویژه زمانی صادق است که نیاز به اشتراک‌گذاری داده‌ها بین صفحات مختلف اپلیکیشن خود دارید، مثلاً داده‌های کاربر. مفهوم *مدیریت وضعیت* همیشه در انواع برنامه‌ها وجود داشته است، اما با افزایش پیچیدگی اپلیکیشن‌های وب، اکنون به یک نکته کلیدی در طول توسعه تبدیل شده است. +با رشد یک اپلیکیشن وب، پیگیری جریان‌های داده‌ای دشوار می‌شود. کدام کد داده‌ها را دریافت می‌کند، کدام صفحه آن‌ها را مصرف می‌کند، کجا و چه زمانی باید به‌روزرسانی شوند... به‌راحتی ممکن است کدی نامرتب ایجاد شود که نگهداری آن دشوار باشد. این موضوع به‌ویژه زمانی صادق است که نیاز به اشتراک‌گذاری داده‌ها بین صفحات مختلف اپلیکیشن خود دارید، مانند داده‌های کاربر. مفهوم *مدیریت وضعیت* همیشه در انواع برنامه‌ها وجود داشته است، اما با افزایش پیچیدگی اپلیکیشن‌های وب، اکنون به یک نکته کلیدی در توسعه تبدیل شده است. -در این بخش پایانی، اپلیکیشنی که ساخته‌ایم را بررسی می‌کنیم تا نحوه مدیریت وضعیت را بازنگری کنیم، به‌گونه‌ای که از تازه‌سازی مرورگر در هر نقطه پشتیبانی کند و داده‌ها را در طول جلسات کاربر حفظ کند. +در این بخش پایانی، اپلیکیشنی که ساخته‌ایم را بررسی می‌کنیم تا نحوه مدیریت وضعیت را بازنگری کنیم، به‌طوری که از تازه‌سازی مرورگر در هر نقطه پشتیبانی کند و داده‌ها را در جلسات کاربری حفظ کند. ### پیش‌نیاز -برای این درس، باید بخش [دریافت داده‌ها](../3-data/README.md) از اپلیکیشن وب را تکمیل کرده باشید. همچنین باید [Node.js](https://nodejs.org) را نصب کرده و [سرور API](../api/README.md) را به‌صورت محلی اجرا کنید تا بتوانید داده‌های حساب را مدیریت کنید. +برای این درس، باید بخش [دریافت داده‌ها](../3-data/README.md) از اپلیکیشن وب را تکمیل کرده باشید. همچنین باید [Node.js](https://nodejs.org) را نصب کنید و [سرور API](../api/README.md) را به‌صورت محلی اجرا کنید تا بتوانید داده‌های حساب را مدیریت کنید. -می‌توانید با اجرای این دستور در یک ترمینال، بررسی کنید که سرور به‌درستی اجرا می‌شود: +برای اطمینان از اجرای صحیح سرور، می‌توانید این دستور را در ترمینال اجرا کنید: ```sh curl http://localhost:5000/api @@ -34,34 +34,34 @@ curl http://localhost:5000/api ## بازنگری مدیریت وضعیت -در [درس قبلی](../3-data/README.md)، یک مفهوم ابتدایی از وضعیت را در اپلیکیشن خود با متغیر سراسری `account` معرفی کردیم که داده‌های بانکی کاربر واردشده را نگه می‌دارد. با این حال، پیاده‌سازی فعلی ما دارای برخی نقص‌ها است. صفحه را در داشبورد تازه‌سازی کنید. چه اتفاقی می‌افتد؟ +در [درس قبلی](../3-data/README.md)، یک مفهوم ابتدایی از وضعیت را در اپلیکیشن خود با متغیر جهانی `account` معرفی کردیم که داده‌های بانکی کاربر وارد شده را ذخیره می‌کند. با این حال، پیاده‌سازی فعلی ما دارای برخی نقص‌ها است. صفحه را در داشبورد تازه‌سازی کنید. چه اتفاقی می‌افتد؟ -سه مشکل در کد فعلی وجود دارد: +کد فعلی ما سه مشکل دارد: - وضعیت حفظ نمی‌شود، زیرا تازه‌سازی مرورگر شما را به صفحه ورود بازمی‌گرداند. -- چندین تابع وضعیت را تغییر می‌دهند. با رشد اپلیکیشن، پیگیری این تغییرات دشوار می‌شود و به‌راحتی می‌توان به‌روزرسانی یکی از آن‌ها را فراموش کرد. +- چندین تابع وضعیت را تغییر می‌دهند. با رشد اپلیکیشن، این موضوع می‌تواند پیگیری تغییرات را دشوار کند و به‌راحتی ممکن است به‌روزرسانی یکی از آن‌ها فراموش شود. - وضعیت پاک نمی‌شود، بنابراین وقتی روی *خروج* کلیک می‌کنید، داده‌های حساب همچنان وجود دارند، حتی اگر در صفحه ورود باشید. -می‌توانیم کد خود را به‌گونه‌ای به‌روزرسانی کنیم که این مشکلات را یکی‌یکی حل کنیم، اما این کار باعث تکرار کد بیشتر و پیچیده‌تر شدن اپلیکیشن می‌شود. یا می‌توانیم چند دقیقه مکث کنیم و استراتژی خود را بازنگری کنیم. +می‌توانیم کد خود را به‌گونه‌ای به‌روزرسانی کنیم که این مشکلات را یکی‌یکی حل کنیم، اما این کار باعث ایجاد تکرار کد بیشتر و پیچیده‌تر شدن اپلیکیشن می‌شود. یا می‌توانیم چند دقیقه مکث کنیم و استراتژی خود را بازنگری کنیم. -> واقعاً چه مشکلاتی را می‌خواهیم اینجا حل کنیم؟ +> واقعاً چه مشکلاتی را می‌خواهیم حل کنیم؟ -[مدیریت وضعیت](https://en.wikipedia.org/wiki/State_management) تماماً درباره یافتن یک رویکرد مناسب برای حل این دو مشکل خاص است: +[مدیریت وضعیت](https://en.wikipedia.org/wiki/State_management) به یافتن یک رویکرد مناسب برای حل این دو مشکل خاص مربوط می‌شود: -- چگونه می‌توان جریان‌های داده در یک اپلیکیشن را قابل‌فهم نگه داشت؟ -- چگونه می‌توان داده‌های وضعیت را همیشه با رابط کاربری هماهنگ نگه داشت (و بالعکس)؟ +- چگونه جریان‌های داده‌ای در یک اپلیکیشن قابل فهم نگه داشته شوند؟ +- چگونه داده‌های وضعیت همیشه با رابط کاربری هماهنگ باشند (و بالعکس)؟ -وقتی این موارد را حل کردید، هر مشکل دیگری که ممکن است داشته باشید یا قبلاً حل شده است یا حل آن آسان‌تر شده است. روش‌های زیادی برای حل این مشکلات وجود دارد، اما ما با یک راه‌حل رایج پیش می‌رویم که شامل **متمرکز کردن داده‌ها و روش‌های تغییر آن‌ها** است. جریان‌های داده به این صورت خواهند بود: +پس از رسیدگی به این موارد، هر مشکل دیگری که ممکن است داشته باشید یا قبلاً حل شده است یا آسان‌تر قابل حل خواهد بود. روش‌های زیادی برای حل این مشکلات وجود دارد، اما ما از یک راه‌حل رایج استفاده می‌کنیم که شامل **متمرکز کردن داده‌ها و روش‌های تغییر آن‌ها** است. جریان‌های داده‌ای به این صورت خواهند بود: -![طرحی که جریان داده‌ها بین HTML، اقدامات کاربر و وضعیت را نشان می‌دهد](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.fa.png) +![طرحی که جریان‌های داده‌ای بین HTML، اقدامات کاربر و وضعیت را نشان می‌دهد](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.fa.png) -> در اینجا بخشی که داده‌ها به‌طور خودکار نمای را به‌روزرسانی می‌کنند پوشش داده نمی‌شود، زیرا این موضوع به مفاهیم پیشرفته‌تر [برنامه‌نویسی واکنشی](https://en.wikipedia.org/wiki/Reactive_programming) مرتبط است. اگر به دنبال یک مطالعه عمیق هستید، این موضوع می‌تواند یک موضوع پیگیری خوب باشد. +> در اینجا بخشی که داده‌ها به‌طور خودکار به‌روزرسانی نمای را تحریک می‌کنند، پوشش داده نمی‌شود، زیرا به مفاهیم پیشرفته‌تر [برنامه‌نویسی واکنشی](https://en.wikipedia.org/wiki/Reactive_programming) مرتبط است. این موضوع می‌تواند یک موضوع پیگیری خوب باشد اگر به دنبال یک بررسی عمیق هستید. -✅ کتابخانه‌های زیادی با رویکردهای مختلف برای مدیریت وضعیت وجود دارند، [Redux](https://redux.js.org) یکی از گزینه‌های محبوب است. به مفاهیم و الگوهای استفاده‌شده نگاهی بیندازید، زیرا اغلب راه خوبی برای یادگیری مشکلات احتمالی است که ممکن است در اپلیکیشن‌های وب بزرگ با آن‌ها مواجه شوید و نحوه حل آن‌ها. +✅ کتابخانه‌های زیادی با رویکردهای مختلف برای مدیریت وضعیت وجود دارند، [Redux](https://redux.js.org) یکی از گزینه‌های محبوب است. نگاهی به مفاهیم و الگوهای استفاده شده بیندازید، زیرا اغلب راه خوبی برای یادگیری مشکلات احتمالی در اپلیکیشن‌های وب بزرگ و نحوه حل آن‌ها است. ### وظیفه -با کمی بازسازی کد شروع می‌کنیم. اعلان `account` را جایگزین کنید: +با کمی بازسازی شروع می‌کنیم. اعلان `account` را جایگزین کنید: ```js let account = null; @@ -75,7 +75,7 @@ let state = { }; ``` -ایده این است که *تمام داده‌های اپلیکیشن خود را در یک شیء وضعیت واحد متمرکز کنیم*. در حال حاضر فقط `account` را در وضعیت داریم، بنابراین تغییر زیادی ایجاد نمی‌کند، اما مسیری برای تکامل ایجاد می‌کند. +ایده این است که *تمام داده‌های اپلیکیشن* خود را در یک شیء وضعیت واحد متمرکز کنیم. در حال حاضر فقط `account` در وضعیت داریم، بنابراین تغییر زیادی ایجاد نمی‌شود، اما راهی برای تکامل ایجاد می‌کند. همچنین باید توابعی که از آن استفاده می‌کنند را به‌روزرسانی کنیم. در توابع `register()` و `login()`، `account = ...` را با `state.account = ...` جایگزین کنید. @@ -85,21 +85,21 @@ let state = { const account = state.account; ``` -این بازسازی به‌تنهایی بهبود زیادی ایجاد نکرد، اما ایده این بود که پایه‌ای برای تغییرات بعدی ایجاد کنیم. +این بازسازی به‌تنهایی بهبود زیادی ایجاد نکرد، اما ایده این بود که پایه‌ای برای تغییرات بعدی ایجاد شود. ## پیگیری تغییرات داده‌ها اکنون که شیء `state` را برای ذخیره داده‌های خود ایجاد کرده‌ایم، گام بعدی متمرکز کردن به‌روزرسانی‌ها است. هدف این است که پیگیری هرگونه تغییر و زمان وقوع آن‌ها آسان‌تر شود. -برای جلوگیری از ایجاد تغییرات در شیء `state`، همچنین یک تمرین خوب است که آن را [*غیرقابل‌تغییر*](https://en.wikipedia.org/wiki/Immutable_object) در نظر بگیریم، به این معنی که اصلاً نمی‌توان آن را تغییر داد. این همچنین به این معنی است که اگر می‌خواهید چیزی را در آن تغییر دهید، باید یک شیء وضعیت جدید ایجاد کنید. با انجام این کار، از اثرات جانبی ناخواسته [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) محافظت می‌کنید و امکان ایجاد ویژگی‌های جدید در اپلیکیشن خود مانند پیاده‌سازی undo/redo را فراهم می‌کنید، در حالی که اشکال‌زدایی را نیز آسان‌تر می‌کنید. برای مثال، می‌توانید هر تغییری که در وضعیت ایجاد می‌شود را ثبت کنید و تاریخچه تغییرات را نگه دارید تا منبع یک باگ را درک کنید. +برای جلوگیری از ایجاد تغییرات در شیء `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/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) برای ایجاد نسخه‌ای غیرقابل‌تغییر از یک شیء استفاده کنید. اگر سعی کنید تغییراتی در یک شیء غیرقابل‌تغییر ایجاد کنید، یک استثنا ایجاد می‌شود. +در جاوااسکریپت، می‌توانید از [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) برای ایجاد نسخه غیرقابل تغییر یک شیء استفاده کنید. اگر سعی کنید تغییراتی در یک شیء غیرقابل تغییر ایجاد کنید، یک استثنا ایجاد خواهد شد. -✅ آیا تفاوت بین یک شیء غیرقابل‌تغییر *سطحی* و *عمیق* را می‌دانید؟ می‌توانید درباره آن [اینجا](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) بخوانید. +✅ آیا تفاوت بین یک شیء غیرقابل تغییر *سطحی* و *عمیق* را می‌دانید؟ می‌توانید درباره آن [اینجا](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) بخوانید. ### وظیفه -یک تابع جدید به نام `updateState()` ایجاد کنید: +بیایید یک تابع جدید `updateState()` ایجاد کنیم: ```js function updateState(property, newData) { @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -در این تابع، یک شیء وضعیت جدید ایجاد می‌کنیم و داده‌ها را از وضعیت قبلی با استفاده از [*عملگر گسترش (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) کپی می‌کنیم. سپس یک ویژگی خاص از شیء وضعیت را با داده‌های جدید با استفاده از [نشانه‌گذاری براکت](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` برای تخصیص بازنویسی می‌کنیم. در نهایت، شیء را قفل می‌کنیم تا از تغییرات جلوگیری کنیم با استفاده از `Object.freeze()`. در حال حاضر فقط ویژگی `account` را در وضعیت ذخیره کرده‌ایم، اما با این رویکرد می‌توانید به تعداد مورد نیاز ویژگی به وضعیت اضافه کنید. +در این تابع، یک شیء وضعیت جدید ایجاد می‌کنیم و داده‌ها را از وضعیت قبلی با استفاده از [عملگر *گسترش (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) کپی می‌کنیم. سپس یک ویژگی خاص از شیء وضعیت را با داده‌های جدید با استفاده از [نشانه‌گذاری براکت](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` برای تخصیص بازنویسی می‌کنیم. در نهایت، شیء را قفل می‌کنیم تا از تغییرات جلوگیری کنیم با استفاده از `Object.freeze()`. در حال حاضر فقط ویژگی `account` در وضعیت ذخیره شده است، اما با این رویکرد می‌توانید به تعداد مورد نیاز ویژگی‌ها را به وضعیت اضافه کنید. همچنین مقداردهی اولیه `state` را به‌روزرسانی می‌کنیم تا مطمئن شویم وضعیت اولیه نیز قفل شده است: @@ -120,21 +120,21 @@ let state = Object.freeze({ }); ``` -سپس تابع `register` را به‌روزرسانی کنید و تخصیص `state.account = result;` را با این جایگزین کنید: +پس از آن، تابع `register` را با جایگزینی تخصیص `state.account = result;` به‌روزرسانی کنید: ```js updateState('account', result); ``` -همین کار را با تابع `login` انجام دهید و تخصیص `state.account = data;` را با این جایگزین کنید: +همین کار را با تابع `login` انجام دهید، تخصیص `state.account = data;` را با: ```js updateState('account', data); ``` -اکنون از این فرصت استفاده می‌کنیم تا مشکل پاک نشدن داده‌های حساب هنگام کلیک کاربر روی *خروج* را برطرف کنیم. +اکنون فرصت را غنیمت می‌شماریم تا مشکل پاک نشدن داده‌های حساب هنگام کلیک کاربر روی *خروج* را حل کنیم. -یک تابع جدید به نام `logout()` ایجاد کنید: +یک تابع جدید `logout()` ایجاد کنید: ```js function logout() { @@ -143,35 +143,35 @@ function logout() { } ``` -در `updateDashboard()`، تغییر مسیر `return navigate('/login');` را با `return logout();` جایگزین کنید. +در `updateDashboard()`، بازگردانی `return navigate('/login');` را با `return logout();` جایگزین کنید. -یک حساب جدید ثبت کنید، خارج شوید و دوباره وارد شوید تا بررسی کنید که همه چیز همچنان به‌درستی کار می‌کند. +یک حساب جدید ثبت کنید، خارج شوید و دوباره وارد شوید تا مطمئن شوید که همه چیز هنوز به‌درستی کار می‌کند. -> نکته: می‌توانید با افزودن `console.log(state)` در انتهای `updateState()` و باز کردن کنسول در ابزارهای توسعه مرورگر خود، به تمام تغییرات وضعیت نگاهی بیندازید. +> نکته: می‌توانید با افزودن `console.log(state)` در انتهای `updateState()` و باز کردن کنسول در ابزارهای توسعه مرورگر خود، تمام تغییرات وضعیت را مشاهده کنید. ## حفظ وضعیت -بیشتر اپلیکیشن‌های وب برای عملکرد صحیح نیاز به حفظ داده‌ها دارند. تمام داده‌های حیاتی معمولاً در یک پایگاه داده ذخیره می‌شوند و از طریق یک سرور API دسترسی پیدا می‌کنند، مانند داده‌های حساب کاربر در مورد ما. اما گاهی اوقات، حفظ برخی داده‌ها در اپلیکیشن کلاینت که در مرورگر شما اجرا می‌شود نیز جالب است، برای تجربه کاربری بهتر یا بهبود عملکرد بارگذاری. +بیشتر اپلیکیشن‌های وب برای عملکرد صحیح نیاز به حفظ داده‌ها دارند. تمام داده‌های حیاتی معمولاً در یک پایگاه داده ذخیره می‌شوند و از طریق یک سرور API دسترسی پیدا می‌کنند، مانند داده‌های حساب کاربری در مورد ما. اما گاهی اوقات، حفظ برخی داده‌ها در اپلیکیشن کلاینت که در مرورگر شما اجرا می‌شود نیز جالب است، برای تجربه کاربری بهتر یا بهبود عملکرد بارگذاری. -هنگامی که می‌خواهید داده‌ها را در مرورگر خود حفظ کنید، چند سؤال مهم وجود دارد که باید از خود بپرسید: +هنگامی که می‌خواهید داده‌ها را در مرورگر خود ذخیره کنید، چند سؤال مهم وجود دارد که باید از خود بپرسید: -- *آیا داده‌ها حساس هستند؟* باید از ذخیره هرگونه داده حساس در کلاینت، مانند رمز عبور کاربر، خودداری کنید. -- *برای چه مدت به این داده‌ها نیاز دارید؟* آیا قصد دارید فقط برای جلسه فعلی به این داده‌ها دسترسی داشته باشید یا می‌خواهید برای همیشه ذخیره شوند؟ +- *آیا داده‌ها حساس هستند؟* باید از ذخیره هرگونه داده حساس در کلاینت، مانند رمزهای عبور کاربر، خودداری کنید. +- *برای چه مدت نیاز دارید این داده‌ها را نگه دارید؟* آیا قصد دارید فقط برای جلسه فعلی به این داده‌ها دسترسی داشته باشید یا می‌خواهید آن‌ها را برای همیشه ذخیره کنید؟ -روش‌های متعددی برای ذخیره اطلاعات در یک اپلیکیشن وب وجود دارد، بسته به آنچه می‌خواهید به دست آورید. برای مثال، می‌توانید از URLها برای ذخیره یک جستجو استفاده کنید و آن را بین کاربران به اشتراک بگذارید. همچنین می‌توانید از [کوکی‌های HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) استفاده کنید اگر داده‌ها نیاز به اشتراک با سرور دارند، مانند اطلاعات [احراز هویت](https://en.wikipedia.org/wiki/Authentication). +روش‌های مختلفی برای ذخیره اطلاعات در یک اپلیکیشن وب وجود دارد، بسته به آنچه می‌خواهید به دست آورید. برای مثال، می‌توانید از URL‌ها برای ذخیره یک پرسش جستجو استفاده کنید و آن را بین کاربران به اشتراک بگذارید. همچنین می‌توانید از [کوکی‌های HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) استفاده کنید اگر داده‌ها نیاز به اشتراک‌گذاری با سرور دارند، مانند اطلاعات [احراز هویت](https://en.wikipedia.org/wiki/Authentication). -گزینه دیگر استفاده از یکی از بسیاری از APIهای مرورگر برای ذخیره داده‌ها است. دو مورد از آن‌ها به‌ویژه جالب هستند: +گزینه دیگر استفاده از یکی از بسیاری از API‌های مرورگر برای ذخیره داده‌ها است. دو مورد از آن‌ها به‌ویژه جالب هستند: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): یک [فروشگاه کلید/مقدار](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) که امکان حفظ داده‌های خاص وب‌سایت فعلی را در جلسات مختلف فراهم می‌کند. داده‌های ذخیره‌شده در آن هرگز منقضی نمی‌شوند. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): این یکی همانند `localStorage` کار می‌کند، با این تفاوت که داده‌های ذخیره‌شده در آن هنگام پایان جلسه (بسته شدن مرورگر) پاک می‌شوند. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): یک [ذخیره‌سازی کلید/مقدار](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) که امکان حفظ داده‌های خاص وب‌سایت فعلی را در جلسات مختلف فراهم می‌کند. داده‌های ذخیره شده در آن هرگز منقضی نمی‌شوند. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): این مورد همانند `localStorage` عمل می‌کند، به جز اینکه داده‌های ذخیره شده در آن هنگام پایان جلسه (زمان بسته شدن مرورگر) پاک می‌شوند. -توجه داشته باشید که هر دوی این APIها فقط اجازه ذخیره [رشته‌ها](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) را می‌دهند. اگر می‌خواهید اشیاء پیچیده را ذخیره کنید، باید آن را به فرمت [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) با استفاده از [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) سریال‌سازی کنید. +توجه داشته باشید که هر دو این API‌ها فقط اجازه ذخیره [رشته‌ها](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) را می‌دهند. اگر می‌خواهید اشیاء پیچیده ذخیره کنید، باید آن‌ها را به فرمت [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) سریال‌سازی کنید با استفاده از [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ اگر می‌خواهید یک اپلیکیشن وب ایجاد کنید که با سرور کار نمی‌کند، همچنین می‌توانید با استفاده از API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) یک پایگاه داده در کلاینت ایجاد کنید. این یکی برای موارد استفاده پیشرفته یا اگر نیاز به ذخیره مقدار زیادی داده دارید، رزرو شده است، زیرا استفاده از آن پیچیده‌تر است. +✅ اگر می‌خواهید یک اپلیکیشن وب ایجاد کنید که با سرور کار نمی‌کند، همچنین امکان ایجاد یک پایگاه داده در کلاینت با استفاده از API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) وجود دارد. این مورد برای موارد استفاده پیشرفته یا اگر نیاز به ذخیره مقدار قابل توجهی داده دارید، رزرو شده است، زیرا استفاده از آن پیچیده‌تر است. ### وظیفه -ما می‌خواهیم کاربران ما تا زمانی که به‌صراحت روی دکمه *خروج* کلیک نکنند، وارد سیستم بمانند، بنابراین از `localStorage` برای ذخیره داده‌های حساب استفاده خواهیم کرد. ابتدا، یک کلید تعریف کنید که برای ذخیره داده‌های خود از آن استفاده خواهیم کرد: +ما می‌خواهیم کاربران ما تا زمانی که به‌طور صریح روی دکمه *خروج* کلیک نکنند، وارد سیستم باقی بمانند، بنابراین از `localStorage` برای ذخیره داده‌های حساب استفاده خواهیم کرد. ابتدا، یک کلید تعریف کنیم که برای ذخیره داده‌های خود استفاده خواهیم کرد. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -با این کار، داده‌های حساب کاربر حفظ می‌شوند و همیشه به‌روز خواهند بود، زیرا قبلاً تمام به‌روزرسانی‌های وضعیت خود را متمرکز کرده‌ایم. اینجاست که شروع به بهره‌برداری از تمام بازسازی‌های قبلی خود می‌کنیم 🙂. +با این کار، داده‌های حساب کاربری حفظ می‌شوند و همیشه به‌روز خواهند بود، همان‌طور که قبلاً تمام به‌روزرسانی‌های وضعیت خود را متمرکز کرده‌ایم. اینجاست که شروع به بهره‌برداری از تمام بازسازی‌های قبلی خود می‌کنیم 🙂. -از آنجا که داده‌ها ذخیره می‌شوند، همچنین باید هنگام بارگذاری اپلیکیشن آن‌ها را بازیابی کنیم. از آنجا که شروع به داشتن کد مقداردهی اولیه بیشتری می‌کنیم، ممکن است ایده خوبی باشد که یک تابع جدید `init` ایجاد کنیم، که شامل کد قبلی ما در انتهای `app.js` نیز باشد: +از آنجا که داده‌ها ذخیره شده‌اند، همچنین باید مراقب بازیابی آن‌ها هنگام بارگذاری اپلیکیشن باشیم. از آنجا که شروع به داشتن کد مقداردهی اولیه بیشتری می‌کنیم، ممکن است ایده خوبی باشد که یک تابع جدید `init` ایجاد کنیم، که شامل کد قبلی ما در انتهای `app.js` نیز باشد: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -در اینجا داده‌های ذخیره‌شده را بازیابی می‌کنیم، و اگر داده‌ای وجود داشته باشد، وضعیت را مطابق آن به‌روزرسانی می‌کنیم. مهم است که این کار را *قبل از* به‌روزرسانی مسیر انجام دهیم، زیرا ممکن است کدی وجود داشته باشد که در طول به‌روزرسانی صفحه به وضعیت متکی باشد. +در اینجا داده‌های ذخیره شده را بازیابی می‌کنیم، و اگر داده‌ای وجود داشته باشد، وضعیت را به‌طور مناسب به‌روزرسانی می‌کنیم. مهم است که این کار را *قبل از* به‌روزرسانی مسیر انجام دهیم، زیرا ممکن است کدی وجود داشته باشد که در طول به‌روزرسانی صفحه به وضعیت وابسته باشد. -همچنین می‌توانیم صفحه *داشبورد* را به‌عنوان صفحه پیش‌فرض اپلیکیشن خود قرار دهیم، زیرا اکنون داده‌های حساب را حفظ می‌کنیم. اگر داده‌ای یافت نشود، داشبورد به هر حال مسئول تغییر مسیر به صفحه *ورود* است. در `updateRoute()`، بازگشت پیش‌فرض `return navigate('/login');` را با `return navigate('/dashboard');` جایگزین کنید. +همچنین می‌توانیم صفحه *داشبورد* را به‌عنوان صفحه پیش‌فرض اپلیکیشن خود قرار دهیم، زیرا اکنون داده‌های حساب را حفظ می‌کنیم. اگر داده‌ای یافت نشود، داشبورد به هر حال مسئولیت هدایت به صفحه *ورود* را بر عهده دارد. در `updateRoute()`، بازگردانی پیش‌فرض `return navigate('/login');` را با `return navigate('/dashboard');` جایگزین کنید. -اکنون وارد اپلیکیشن شوید و سعی کنید صفحه را تازه‌سازی کنید. باید در داشبورد بمانید. با این به‌روزرسانی، تمام مشکلات اولیه خود را برطرف کرده‌ایم... +اکنون وارد اپلیکیشن شوید و صفحه را تازه‌سازی کنید. باید در داشبورد باقی بمانید. با این به‌روزرسانی، تمام مشکلات اولیه خود را حل کرده‌ایم... -## تازه‌سازی داده‌ها +## به‌روزرسانی داده‌ها ...اما ممکن است یک مشکل جدید ایجاد کرده باشیم. اوه! -به داشبورد بروید و از حساب `test` استفاده کنید، سپس این دستور را در یک ترمینال اجرا کنید تا یک تراکنش جدید ایجاد کنید: +با حساب `test` به داشبورد بروید، سپس این دستور را در ترمینال اجرا کنید تا یک تراکنش جدید ایجاد کنید: ```sh curl --request POST \ @@ -221,15 +221,15 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -اکنون سعی کنید صفحه داشبورد را در مرورگر تازه‌سازی کنید. چه اتفاقی می‌افتد؟ آیا تراکنش جدید را می‌بینید؟ +اکنون صفحه داشبورد خود را در مرورگر تازه‌سازی کنید. چه اتفاقی می‌افتد؟ آیا تراکنش جدید را می‌بینید؟ -وضعیت به لطف `localStorage` به‌طور نامحدود حفظ می‌شود، اما این همچنین به این معنی است که تا زمانی که از اپلیکیشن خارج نشوید و دوباره وارد نشوید، هرگز به‌روزرسانی نمی‌شود! +وضعیت به لطف `localStorage` به‌طور نامحدود حفظ می‌شود، اما این همچنین به این معنی است که تا زمانی که از اپلیکیشن خارج نشوید و دوباره وارد شوید، هرگز به‌روزرسانی نمی‌شود! -یک استراتژی ممکن برای رفع این مشکل این است که هر بار که داشبورد بارگذاری می‌شود، داده‌های حساب را دوباره بارگذاری کنیم تا از داده‌های قدیمی جلوگیری کنیم. +یک استراتژی ممکن برای رفع این مشکل این است که داده‌های حساب را هر بار که داشبورد بارگذاری می‌شود، دوباره بارگذاری کنیم تا از داده‌های قدیمی جلوگیری کنیم. ### وظیفه -یک تابع جدید به نام `updateAccountData` ایجاد کنید: +یک تابع جدید `updateAccountData` ایجاد کنید: ```js async function updateAccountData() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -این یکی داده‌های حساب را به‌روزرسانی می‌کند، سپس HTML صفحه داشبورد را به‌روزرسانی می‌کند. این همان چیزی است که باید هنگام بارگذاری مسیر داشبورد فراخوانی کنیم. تعریف مسیر را با این به‌روزرسانی کنید: +این تابع داده‌های حساب را به‌روزرسانی می‌کند، سپس HTML صفحه داشبورد را به‌روزرسانی می‌کند. این همان چیزی است که باید هنگام بارگذاری مسیر داشبورد فراخوانی شود. تعریف مسیر را با این مورد به‌روزرسانی کنید: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -اکنون سعی کنید داشبورد را تازه‌سازی کنید، باید داده‌های حساب به‌روزرسانی‌شده را نمایش دهد. +اکنون داشبورد را تازه‌سازی کنید، باید داده‌های حساب به‌روزرسانی شده را نمایش دهد. --- ## 🚀 چالش -اکنون که هر بار که داشبورد بارگذاری می‌شود داده‌های حساب را دوباره بارگذاری می‌کنیم، آیا فکر می‌کنید هنوز نیاز داریم *تمام داده‌های حساب* را حفظ کنیم؟ +اکنون که داده‌های حساب را هر بار که داشبورد بارگذاری می‌شود دوباره بارگذاری می‌کنیم، آیا فکر می‌کنید هنوز نیاز داریم *تمام داده‌های حساب* را حفظ کنیم؟ -سعی کنید با هم کار کنید تا آنچه را که از `localStorage` ذخیره و بارگذاری می‌شود تغییر دهید تا فقط شامل آنچه که برای عملکرد اپلیکیشن کاملاً ضروری است باشد. +سعی کنید با هم کار کنید تا آنچه از `localStorage` ذخیره و بارگذاری می‌شود را تغییر دهید تا فقط شامل مواردی باشد که برای عملکرد اپلیکیشن کاملاً ضروری هستند. ## آزمون پس از درس - -[آزمون پس از درس](https://ff-quizzes.netlify.app/web/quiz/48) +[آزمون پس از سخنرانی](https://ff-quizzes.netlify.app/web/quiz/48) ## تکلیف -[پیاده‌سازی "افزودن تراکنش" در دیالوگ](assignment.md) -در اینجا یک نمونه نتیجه پس از تکمیل وظیفه آورده شده است: +[پیاده‌سازی دیالوگ "افزودن تراکنش"](assignment.md) + +در اینجا یک نمونه نتیجه پس از تکمیل تکلیف آورده شده است: ![تصویری که یک نمونه دیالوگ "افزودن تراکنش" را نشان می‌دهد](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.fa.png) --- **سلب مسئولیت**: -این سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما برای دقت تلاش می‌کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌هایی باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، ترجمه حرفه‌ای انسانی توصیه می‌شود. ما هیچ مسئولیتی در قبال سوءتفاهم‌ها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم. \ No newline at end of file +این سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما برای دقت تلاش می‌کنیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است حاوی خطاها یا نادرستی‌هایی باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفه‌ای انسانی توصیه می‌شود. ما مسئولیتی در قبال هرگونه سوءتفاهم یا تفسیر نادرست ناشی از استفاده از این ترجمه نداریم. \ No newline at end of file diff --git a/translations/fi/7-bank-project/4-state-management/README.md b/translations/fi/7-bank-project/4-state-management/README.md index 00230c9af..1ac58bc33 100644 --- a/translations/fi/7-bank-project/4-state-management/README.md +++ b/translations/fi/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ # בניית אפליקציית בנקאות חלק 4: מושגים בניהול מצב -## שאלון לפני השיעור +## חידון לפני ההרצאה -[שאלון לפני השיעור](https://ff-quizzes.netlify.app/web/quiz/47) +[חידון לפני ההרצאה](https://ff-quizzes.netlify.app/web/quiz/47) -### הקדמה +### מבוא -ככל שאפליקציית ווב גדלה, קשה יותר לעקוב אחר כל זרימות הנתונים. איזה קוד מקבל את הנתונים, איזה עמוד צורך אותם, איפה ומתי צריך לעדכן אותם... קל להגיע לקוד מבולגן שקשה לתחזק. זה נכון במיוחד כשצריך לשתף נתונים בין עמודים שונים באפליקציה, למשל נתוני משתמש. מושג *ניהול מצב* תמיד היה קיים בכל סוגי התוכניות, אבל ככל שאפליקציות ווב ממשיכות לגדול במורכבות, זה הפך לנקודה מרכזית שיש לחשוב עליה במהלך הפיתוח. +ככל שאפליקציית ווב גדלה, נעשה מאתגר לעקוב אחרי כל זרימות הנתונים. איזה קוד מקבל את הנתונים, איזו דף צורך אותם, היכן ומתי צריך לעדכן אותם... קל מאוד להגיע לקוד מבולגן שקשה לתחזק. זה נכון במיוחד כאשר יש צורך לשתף נתונים בין דפים שונים באפליקציה, כמו נתוני משתמש. המושג של *ניהול מצב* תמיד היה קיים בכל סוגי התוכניות, אך ככל שאפליקציות ווב נעשות מורכבות יותר, זהו כעת נקודה מרכזית שיש לחשוב עליה במהלך הפיתוח. -בחלק האחרון הזה, נבחן את האפליקציה שבנינו כדי לחשוב מחדש על איך המצב מנוהל, כך שתתמוך ברענון הדפדפן בכל נקודה ותשמור נתונים בין סשנים של משתמשים. +בחלק האחרון הזה, נבחן מחדש את האפליקציה שבנינו כדי לחשוב מחדש על ניהול המצב, כך שתתמוך ברענון הדפדפן בכל נקודה ותשמור נתונים בין סשנים של משתמשים. ### דרישות מקדימות -עליך להשלים את חלק [שאיבת הנתונים](../3-data/README.md) של אפליקציית הווב עבור שיעור זה. כמו כן, עליך להתקין [Node.js](https://nodejs.org) ולהריץ את [שרת ה-API](../api/README.md) באופן מקומי כדי שתוכל לנהל נתוני חשבון. +עליך להשלים את החלק של [שליפת נתונים](../3-data/README.md) באפליקציית הווב עבור שיעור זה. כמו כן, עליך להתקין את [Node.js](https://nodejs.org) ולהריץ את [שרת ה-API](../api/README.md) באופן מקומי כדי שתוכל לנהל נתוני חשבון. -ניתן לבדוק שהשרת פועל כראוי על ידי ביצוע הפקודה הזו בטרמינל: +תוכל לבדוק שהשרת פועל כראוי על ידי ביצוע הפקודה הזו בטרמינל: ```sh curl http://localhost:5000/api @@ -34,34 +34,34 @@ curl http://localhost:5000/api ## חשיבה מחדש על ניהול מצב -בשיעור [הקודם](../3-data/README.md), הצגנו מושג בסיסי של מצב באפליקציה שלנו עם המשתנה הגלובלי `account` שמכיל את נתוני הבנק של המשתמש המחובר כרגע. עם זאת, היישום הנוכחי שלנו מכיל כמה פגמים. נסה לרענן את העמוד כשאתה נמצא בלוח הבקרה. מה קורה? +בשיעור הקודם ([כאן](../3-data/README.md)), הצגנו מושג בסיסי של מצב באפליקציה שלנו עם המשתנה הגלובלי `account` שמכיל את נתוני הבנק של המשתמש המחובר כרגע. עם זאת, ליישום הנוכחי שלנו יש כמה פגמים. נסה לרענן את הדף כשאתה נמצא בלוח הבקרה. מה קורה? ישנן 3 בעיות בקוד הנוכחי: -- המצב אינו נשמר, רענון הדפדפן מחזיר אותך לעמוד ההתחברות. -- ישנן פונקציות רבות שמעדכנות את המצב. ככל שהאפליקציה גדלה, זה יכול להקשות על מעקב אחר השינויים וקל לשכוח לעדכן אחת מהן. -- המצב אינו מנוקה, כך שכאשר אתה לוחץ על *התנתקות*, נתוני החשבון עדיין שם למרות שאתה נמצא בעמוד ההתחברות. +- המצב אינו נשמר, ורענון הדפדפן מחזיר אותך לדף ההתחברות. +- ישנן פונקציות רבות שמעדכנות את המצב. ככל שהאפליקציה גדלה, זה יכול להקשות על מעקב אחר השינויים וקל לשכוח לעדכן משהו. +- המצב אינו מתנקה, כך שכאשר אתה לוחץ על *התנתקות*, נתוני החשבון עדיין שם למרות שאתה בדף ההתחברות. -יכולנו לעדכן את הקוד שלנו כדי להתמודד עם הבעיות הללו אחת אחת, אבל זה היה יוצר כפילות קוד רבה ומסבך את האפליקציה יותר. או שאנחנו יכולים לעצור לכמה דקות ולחשוב מחדש על האסטרטגיה שלנו. +יכולנו לעדכן את הקוד שלנו כדי לטפל בבעיות הללו אחת אחת, אבל זה ייצור כפילויות קוד ויהפוך את האפליקציה למורכבת יותר וקשה יותר לתחזוקה. או שנוכל לעצור לכמה דקות ולחשוב מחדש על האסטרטגיה שלנו. > אילו בעיות אנחנו באמת מנסים לפתור כאן? -[ניהול מצב](https://en.wikipedia.org/wiki/State_management) עוסק במציאת גישה טובה לפתרון שתי הבעיות הספציפיות הללו: +[ניהול מצב](https://en.wikipedia.org/wiki/State_management) עוסק במציאת גישה טובה לפתרון שתי הבעיות העיקריות הללו: - איך לשמור על זרימות הנתונים באפליקציה מובנות? -- איך לשמור על נתוני המצב תמיד מסונכרנים עם ממשק המשתמש (ולהפך)? +- איך לשמור על נתוני המצב תמיד מסונכרנים עם ממשק המשתמש (ולהיפך)? -ברגע שתטפל בזה, כל בעיה אחרת שעשויה להיות לך עשויה כבר להיפתר או להפוך לקלה יותר לפתרון. ישנן גישות רבות לפתרון בעיות אלו, אבל נבחר פתרון נפוץ שמורכב מ**מרכזיות הנתונים והדרכים לשנות אותם**. זרימות הנתונים ייראו כך: +ברגע שטיפלת בבעיות הללו, כל בעיה אחרת עשויה כבר להיפתר או להיות קלה יותר לפתרון. ישנן גישות רבות לפתרון הבעיות הללו, אבל נבחר בפתרון נפוץ שמורכב מ**ריכוז הנתונים והדרכים לשנות אותם**. זרימות הנתונים ייראו כך: -![סכמה שמראה את זרימות הנתונים בין ה-HTML, פעולות המשתמש והמצב](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.he.png) +![סכימה שמראה את זרימות הנתונים בין ה-HTML, פעולות המשתמש והמצב](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.he.png) -> לא נעסוק כאן בחלק שבו הנתונים מעדכנים את התצוגה באופן אוטומטי, מכיוון שזה קשור למושגים מתקדמים יותר של [תכנות תגובתי](https://en.wikipedia.org/wiki/Reactive_programming). זה נושא מעמיק טוב אם אתה מעוניין. +> לא נעסוק כאן בחלק שבו הנתונים מעדכנים אוטומטית את התצוגה, שכן זה קשור למושגים מתקדמים יותר של [תכנות תגובתי](https://en.wikipedia.org/wiki/Reactive_programming). זהו נושא מעמיק טוב אם תרצה להעמיק. -✅ יש הרבה ספריות עם גישות שונות לניהול מצב, [Redux](https://redux.js.org) היא אפשרות פופולרית. כדאי להסתכל על המושגים והתבניות שבהם משתמשים, שכן זה לעיתים קרובות דרך טובה ללמוד על בעיות פוטנציאליות שאתה עשוי להתמודד איתן באפליקציות ווב גדולות וכיצד ניתן לפתור אותן. +✅ ישנן ספריות רבות עם גישות שונות לניהול מצב, [Redux](https://redux.js.org) היא אפשרות פופולרית. כדאי להכיר את המושגים והתבניות שבהן משתמשים, שכן זהו לעיתים קרובות דרך טובה ללמוד על בעיות פוטנציאליות שאתה עשוי להיתקל בהן באפליקציות ווב גדולות וכיצד ניתן לפתור אותן. ### משימה -נתחיל עם קצת ריפקטורינג. החלף את ההצהרה של `account`: +נתחיל עם קצת רפקטורינג. החלף את ההצהרה `account`: ```js let account = null; @@ -75,7 +75,7 @@ let state = { }; ``` -הרעיון הוא *לרכז* את כל נתוני האפליקציה שלנו באובייקט מצב יחיד. כרגע יש לנו רק `account` במצב, כך שזה לא משנה הרבה, אבל זה יוצר דרך להתפתחויות עתידיות. +הרעיון הוא *לרכז* את כל נתוני האפליקציה שלנו באובייקט מצב יחיד. כרגע יש לנו רק `account` במצב, כך שזה לא משנה הרבה, אבל זה יוצר בסיס לשינויים עתידיים. עלינו גם לעדכן את הפונקציות שמשתמשות בו. בפונקציות `register()` ו-`login()`, החלף `account = ...` ב-`state.account = ...`; @@ -85,17 +85,17 @@ let state = { const account = state.account; ``` -הריפקטורינג הזה בפני עצמו לא הביא שיפורים רבים, אבל הרעיון היה להניח את היסודות לשינויים הבאים. +הרפקטורינג הזה בפני עצמו לא הביא שיפורים רבים, אבל הרעיון היה להניח את היסודות לשינויים הבאים. ## מעקב אחר שינויים בנתונים -עכשיו כששמנו במקום את אובייקט `state` לאחסון הנתונים שלנו, השלב הבא הוא לרכז את העדכונים. המטרה היא להקל על מעקב אחר כל שינוי ומתי הוא מתרחש. +עכשיו, כשיש לנו את אובייקט ה-`state` לאחסון הנתונים שלנו, השלב הבא הוא לרכז את העדכונים. המטרה היא להקל על המעקב אחר כל שינוי ומתי הוא מתרחש. -כדי להימנע משינויים באובייקט `state`, זה גם נוהג טוב לשקול אותו [*בלתי ניתן לשינוי*](https://en.wikipedia.org/wiki/Immutable_object), כלומר שהוא לא יכול להיות שונה כלל. זה גם אומר שאתה צריך ליצור אובייקט מצב חדש אם אתה רוצה לשנות משהו בו. על ידי כך, אתה בונה הגנה מפני [תופעות לוואי](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) לא רצויות, ופותח אפשרויות לתכונות חדשות באפליקציה שלך כמו יישום undo/redo, תוך גם הקלה על איתור באגים. למשל, תוכל לרשום כל שינוי שנעשה במצב ולשמור היסטוריה של השינויים כדי להבין את מקור הבאג. +כדי למנוע שינויים באובייקט ה-`state`, זה גם נוהג טוב לשקול אותו כ[*בלתי ניתן לשינוי*](https://en.wikipedia.org/wiki/Immutable_object), כלומר שלא ניתן לשנות אותו כלל. זה גם אומר שעליך ליצור אובייקט מצב חדש אם ברצונך לשנות משהו בו. על ידי כך, אתה בונה הגנה מפני [תופעות לוואי](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) לא רצויות, ופותח אפשרויות לתכונות חדשות באפליקציה שלך כמו יישום פעולות ביטול/חזרה, תוך הקלה על איתור באגים. לדוגמה, תוכל לרשום כל שינוי שנעשה במצב ולשמור היסטוריה של השינויים כדי להבין את מקור הבאג. -ב-JavaScript, ניתן להשתמש ב-[`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) כדי ליצור גרסה בלתי ניתנת לשינוי של אובייקט. אם תנסה לבצע שינויים באובייקט בלתי ניתן לשינוי, תתעורר חריגה. +ב-JavaScript, תוכל להשתמש ב-[`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) כדי ליצור גרסה בלתי ניתנת לשינוי של אובייקט. אם תנסה לבצע שינויים באובייקט בלתי ניתן לשינוי, תתעורר חריגה. -✅ האם אתה יודע את ההבדל בין אובייקט בלתי ניתן לשינוי *שטחי* לבין *עמוק*? תוכל לקרוא על כך [כאן](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ האם אתה יודע מה ההבדל בין אובייקט בלתי ניתן לשינוי *שטחי* לבין *עמוק*? תוכל לקרוא על כך [כאן](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### משימה @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -בפונקציה זו, אנחנו יוצרים אובייקט מצב חדש ומעתיקים נתונים מהמצב הקודם באמצעות [*אופרטור הפיזור (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). לאחר מכן אנחנו מחליפים תכונה מסוימת של אובייקט המצב עם הנתונים החדשים באמצעות [הסימון המרובע](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` להקצאה. לבסוף, אנחנו נועלים את האובייקט כדי למנוע שינויים באמצעות `Object.freeze()`. כרגע יש לנו רק את התכונה `account` במצב, אבל עם הגישה הזו ניתן להוסיף כמה תכונות שצריך במצב. +בפונקציה הזו, אנחנו יוצרים אובייקט מצב חדש ומעתיקים נתונים מהמצב הקודם באמצעות [*אופרטור הפיזור (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). לאחר מכן, אנו מחליפים מאפיין מסוים של אובייקט המצב עם הנתונים החדשים באמצעות [הערת סוגריים](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` לצורך השמה. לבסוף, אנו נועלים את האובייקט כדי למנוע שינויים באמצעות `Object.freeze()`. כרגע יש לנו רק את המאפיין `account` במצב, אבל עם הגישה הזו תוכל להוסיף כמה מאפיינים שתרצה. -נעדכן גם את אתחול המצב כדי לוודא שהמצב ההתחלתי נעול גם הוא: +נעדכן גם את האתחול של `state` כדי לוודא שהמצב ההתחלתי נעול גם הוא: ```js let state = Object.freeze({ @@ -120,19 +120,19 @@ let state = Object.freeze({ }); ``` -לאחר מכן, עדכן את הפונקציה `register` על ידי החלפת ההקצאה `state.account = result;` ב: +לאחר מכן, עדכן את פונקציית `register` על ידי החלפת ההשמה `state.account = result;` ב: ```js updateState('account', result); ``` -עשה את אותו הדבר עם הפונקציה `login`, החלף `state.account = data;` ב: +עשה את אותו הדבר עם פונקציית `login`, והחלף `state.account = data;` ב: ```js updateState('account', data); ``` -ננצל את ההזדמנות כדי לתקן את הבעיה של נתוני החשבון שלא מתנקים כאשר המשתמש לוחץ על *התנתקות*. +כעת ננצל את ההזדמנות לתקן את הבעיה של אי ניקוי נתוני החשבון כאשר המשתמש לוחץ על *התנתקות*. צור פונקציה חדשה בשם `logout()`: @@ -145,47 +145,47 @@ function logout() { ב-`updateDashboard()`, החלף את ההפניה `return navigate('/login');` ב-`return logout()`; -נסה לרשום חשבון חדש, להתנתק ולהתחבר שוב כדי לבדוק שהכל עדיין עובד כראוי. +נסה להירשם לחשבון חדש, להתנתק ולהתחבר שוב כדי לבדוק שהכול עדיין עובד כראוי. -> טיפ: תוכל להסתכל על כל השינויים במצב על ידי הוספת `console.log(state)` בתחתית `updateState()` ופתיחת הקונסול בכלי הפיתוח של הדפדפן שלך. +> טיפ: תוכל לעקוב אחרי כל השינויים במצב על ידי הוספת `console.log(state)` בתחתית `updateState()` ופתיחת הקונסולה בכלי הפיתוח של הדפדפן שלך. ## שמירת המצב -רוב אפליקציות הווב צריכות לשמור נתונים כדי לעבוד כראוי. כל הנתונים הקריטיים בדרך כלל נשמרים בבסיס נתונים ונגישים דרך שרת API, כמו נתוני החשבון של המשתמש במקרה שלנו. אבל לפעמים, זה גם מעניין לשמור נתונים באפליקציה בצד הלקוח שרצה בדפדפן, לשיפור חוויית המשתמש או לשיפור ביצועי הטעינה. +רוב אפליקציות הווב צריכות לשמור נתונים כדי לעבוד כראוי. כל הנתונים הקריטיים נשמרים בדרך כלל במסד נתונים ונגישים דרך API של שרת, כמו נתוני חשבון המשתמש במקרה שלנו. אבל לפעמים, זה גם מעניין לשמור נתונים מסוימים באפליקציה בצד הלקוח שרצה בדפדפן שלך, לשיפור חוויית המשתמש או לשיפור ביצועי הטעינה. -כשאתה רוצה לשמור נתונים בדפדפן שלך, יש כמה שאלות חשובות שכדאי לשאול את עצמך: +כשאתה רוצה לשמור נתונים בדפדפן שלך, יש כמה שאלות חשובות שעליך לשאול את עצמך: -- *האם הנתונים רגישים?* כדאי להימנע משמירת נתונים רגישים בצד הלקוח, כמו סיסמאות משתמש. -- *לכמה זמן אתה צריך לשמור את הנתונים האלה?* האם אתה מתכנן לגשת לנתונים רק עבור הסשן הנוכחי או שאתה רוצה שהם יישמרו לנצח? +- *האם הנתונים רגישים?* עליך להימנע משמירת נתונים רגישים בצד הלקוח, כמו סיסמאות משתמש. +- *לכמה זמן אתה צריך לשמור את הנתונים הללו?* האם אתה מתכנן לגשת לנתונים הללו רק במהלך הסשן הנוכחי או שאתה רוצה שהם יישמרו לנצח? -ישנן דרכים רבות לאחסן מידע בתוך אפליקציית ווב, תלוי במה שאתה רוצה להשיג. למשל, ניתן להשתמש ב-URLs כדי לשמור שאילתת חיפוש, ולהפוך אותה לשיתופית בין משתמשים. ניתן גם להשתמש ב-[עוגיות HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) אם הנתונים צריכים להיות משותפים עם השרת, כמו מידע [אימות](https://en.wikipedia.org/wiki/Authentication). +ישנן דרכים רבות לאחסן מידע בתוך אפליקציית ווב, תלוי במה שאתה רוצה להשיג. לדוגמה, תוכל להשתמש בכתובות URL כדי לשמור שאילתת חיפוש, ולהפוך אותה לשיתופית בין משתמשים. תוכל גם להשתמש ב-[עוגיות HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) אם הנתונים צריכים להיות משותפים עם השרת, כמו מידע על [אימות](https://en.wikipedia.org/wiki/Authentication). אפשרות נוספת היא להשתמש באחת מה-APIs הרבות של הדפדפן לאחסון נתונים. שתיים מהן מעניינות במיוחד: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [חנות מפתח/ערך](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) שמאפשרת לשמור נתונים ספציפיים לאתר הנוכחי בין סשנים שונים. הנתונים שנשמרים בה לעולם לא פגים. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): זו עובדת באותו אופן כמו `localStorage` מלבד שהנתונים שנשמרים בה נמחקים כאשר הסשן מסתיים (כאשר הדפדפן נסגר). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [מאגר מפתחות/ערכים](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) שמאפשר לשמור נתונים ספציפיים לאתר הנוכחי בין סשנים שונים. הנתונים שנשמרים בו אינם פגים לעולם. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): זה עובד כמו `localStorage` פרט לכך שהנתונים שנשמרים בו נמחקים כאשר הסשן מסתיים (כאשר הדפדפן נסגר). -שימו לב ששתי ה-APIs הללו מאפשרות לשמור רק [מחרוזות](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). אם תרצה לשמור אובייקטים מורכבים, תצטרך לסדר אותם לפורמט [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) באמצעות [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +שימו לב ששני ה-APIs הללו מאפשרים לשמור רק [מחרוזות](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). אם ברצונך לשמור אובייקטים מורכבים, תצטרך לסדר אותם לפורמט [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) באמצעות [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ אם תרצה ליצור אפליקציית ווב שלא עובדת עם שרת, ניתן גם ליצור בסיס נתונים בצד הלקוח באמצעות [API של `IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). זה שמור למקרים מתקדמים או אם אתה צריך לשמור כמות משמעותית של נתונים, מכיוון שזה מורכב יותר לשימוש. +✅ אם ברצונך ליצור אפליקציית ווב שאינה עובדת עם שרת, ניתן גם ליצור מסד נתונים בצד הלקוח באמצעות [API של `IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). זה שמור למקרי שימוש מתקדמים או אם אתה צריך לשמור כמות משמעותית של נתונים, שכן זה מורכב יותר לשימוש. ### משימה -אנחנו רוצים שהמשתמשים שלנו יישארו מחוברים עד שהם לוחצים באופן מפורש על כפתור *התנתקות*, אז נשתמש ב-`localStorage` כדי לשמור את נתוני החשבון. קודם כל, נגדיר מפתח שנשתמש בו כדי לשמור את הנתונים שלנו. +אנחנו רוצים שהמשתמשים שלנו יישארו מחוברים עד שהם לוחצים במפורש על כפתור *התנתקות*, ולכן נשתמש ב-`localStorage` כדי לשמור את נתוני החשבון. ראשית, נגדיר מפתח שנשתמש בו לשמירת הנתונים שלנו. ```js const storageKey = 'savedAccount'; ``` -לאחר מכן, הוסף את השורה הזו בסוף הפונקציה `updateState()`: +לאחר מכן, הוסף את השורה הזו בסוף פונקציית `updateState()`: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -עם זה, נתוני החשבון של המשתמש יישמרו ותמיד יהיו מעודכנים כפי שריכזנו קודם את כל עדכוני המצב שלנו. כאן אנחנו מתחילים ליהנות מכל הריפקטורינג הקודם שלנו 🙂. +עם זה, נתוני חשבון המשתמש יישמרו ותמיד יהיו מעודכנים, כפי שריכזנו קודם את כל עדכוני המצב שלנו. כאן אנחנו מתחילים ליהנות מכל הרפקטורינג הקודם שלנו 🙂. -מכיוון שהנתונים נשמרים, עלינו גם לדאוג לשחזר אותם כאשר האפליקציה נטענת. מכיוון שאנחנו מתחילים לקבל יותר קוד אתחול, זה עשוי להיות רעיון טוב ליצור פונקציה חדשה בשם `init`, שכוללת גם את הקוד הקודם שלנו בתחתית `app.js`: +מכיוון שהנתונים נשמרים, עלינו גם לדאוג לשחזר אותם כאשר האפליקציה נטענת. מכיוון שנתחיל לקבל יותר קוד אתחול, ייתכן שזה רעיון טוב ליצור פונקציה חדשה בשם `init`, שכוללת גם את הקוד הקודם בתחתית `app.js`: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -כאן אנחנו משחזרים את הנתונים שנשמרו, ואם יש כאלה אנחנו מעדכנים את המצב בהתאם. חשוב לעשות זאת *לפני* עדכון המסלול, מכיוון שייתכן שיש קוד שמסתמך על המצב במהלך עדכון העמוד. +כאן אנו משחזרים את הנתונים שנשמרו, ואם יש כאלה אנו מעדכנים את המצב בהתאם. חשוב לעשות זאת *לפני* עדכון הנתיב, שכן ייתכן שיש קוד שמסתמך על המצב במהלך עדכון הדף. -אנחנו יכולים גם להפוך את עמוד *לוח הבקרה* לעמוד ברירת המחדל של האפליקציה שלנו, מכיוון שאנחנו עכשיו שומרים את נתוני החשבון. אם לא נמצאו נתונים, לוח הבקרה דואג להפנות לעמוד *התחברות* בכל מקרה. ב-`updateRoute()`, החלף את ברירת המחדל `return navigate('/login');` ב-`return navigate('/dashboard');`. +אנחנו גם יכולים להפוך את דף *לוח הבקרה* לדף ברירת המחדל של האפליקציה שלנו, מכיוון שעכשיו אנחנו שומרים את נתוני החשבון. אם לא נמצאו נתונים, לוח הבקרה דואג להפניה לדף *התחברות* בכל מקרה. ב-`updateRoute()`, החלף את ברירת המחדל `return navigate('/login');` ב-`return navigate('/dashboard');`. -עכשיו התחבר לאפליקציה ונסה לרענן את העמוד. אתה אמור להישאר בלוח הבקרה. עם העדכון הזה טיפלנו בכל הבעיות הראשוניות שלנו... +כעת התחבר לאפליקציה ונסה לרענן את הדף. אתה אמור להישאר בלוח הבקרה. עם העדכון הזה טיפלנו בכל הבעיות הראשוניות שלנו... ## רענון הנתונים ...אבל ייתכן שגם יצרנו בעיה חדשה. אופס! -עבור ללוח הבקרה באמצעות החשבון `test`, ואז הרץ את הפקודה הזו בטרמינל כדי ליצור עסקה חדשה: +עבור ללוח הבקרה באמצעות חשבון `test`, ואז הרץ את הפקודה הזו בטרמינל כדי ליצור עסקה חדשה: ```sh curl --request POST \ @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -נסה לרענן את עמוד לוח הבקרה בדפדפן עכשיו. מה קורה? האם אתה רואה את העסקה החדשה? +נסה לרענן את דף לוח הבקרה בדפדפן עכשיו. מה קורה? האם אתה רואה את העסקה החדשה? -המצב נשמר ללא הגבלה בזכות ה-`localStorage`, אבל זה גם אומר שהוא לעולם לא מתעדכן עד שתתנתק מהאפליקציה ותתחבר שוב! +המצב נשמר ללא הגבלת זמן בזכות ה-`localStorage`, אבל זה גם אומר שהוא אף פעם לא מתעדכן עד שאתה מתנתק מהאפליקציה ומתחבר שוב! אסטרטגיה אפשרית לתקן זאת היא לטעון מחדש את נתוני החשבון בכל פעם שלוח הבקרה נטען, כדי להימנע מנתונים מיושנים. @@ -258,7 +258,7 @@ async function refresh() { } ``` -זו מעדכנת את נתוני החשבון, ואז דואגת לעדכן את ה-HTML של עמוד לוח הבקרה. זה מה שאנחנו צריכים לקרוא כאשר מסלול לוח הבקרה נטען. עדכן את הגדרת המסלול עם: +פונקציה זו מעדכנת את נתוני החשבון, ואז דואגת לעדכן את ה-HTML של דף לוח הבקרה. זה מה שאנחנו צריכים לקרוא כאשר נתיב לוח הבקרה נטען. עדכן את הגדרת הנתיב עם: ```js const routes = { @@ -273,22 +273,22 @@ const routes = { ## 🚀 אתגר -עכשיו כשאנחנו טוענים מחדש את נתוני החשבון בכל פעם שלוח הבקרה נטען, האם לדעתך אנחנו עדיין צריכים לשמור *את כל נתוני החשבון*? +עכשיו, כשאנחנו טוענים מחדש את נתוני החשבון בכל פעם שלוח הבקרה נטען, האם לדעתך אנחנו עדיין צריכים לשמור *את כל נתוני החשבון*? -נסה לעבוד יחד כדי לשנות מה נשמר ומה נטען מ-`localStorage` כך שיכלול רק את מה שדרוש באופן מוחלט כדי שהאפליקציה תעבוד. +נסה לעבוד יחד כדי לשנות מה נשמר ומה נטען מ-`localStorage` כך שיכלול רק את מה שחיוני לאפליקציה לעבוד. -## שאלון אחרי השיעור - -[שאלון אחרי השיעור](https://ff-quizzes.netlify.app/web/quiz/48) +## חידון לאחר ההרצאה +[שאלון לאחר ההרצאה](https://ff-quizzes.netlify.app/web/quiz/48) ## משימה -[מימוש דיאלוג "הוסף עסקה"](assignment.md) -הנה דוגמה לתוצאה לאחר השלמת המשימה: +[מימוש דיאלוג "הוספת עסקה"](assignment.md) + +להלן דוגמה לתוצאה לאחר השלמת המשימה: -![צילום מסך המציג דיאלוג לדוגמה של "הוסף עסקה"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.he.png) +![צילום מסך המציג דוגמה לדיאלוג "הוספת עסקה"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.he.png) --- **כתב ויתור**: -מסמך זה תורגם באמצעות שירות תרגום מבוסס בינה מלאכותית [Co-op Translator](https://github.com/Azure/co-op-translator). למרות שאנו שואפים לדיוק, יש לקחת בחשבון שתרגומים אוטומטיים עשויים להכיל שגיאות או אי-דיוקים. המסמך המקורי בשפתו המקורית נחשב למקור הסמכותי. למידע קריטי, מומלץ להשתמש בתרגום מקצועי על ידי בני אדם. איננו נושאים באחריות לכל אי-הבנה או פרשנות שגויה הנובעת משימוש בתרגום זה. \ No newline at end of file +מסמך זה תורגם באמצעות שירות תרגום מבוסס בינה מלאכותית [Co-op Translator](https://github.com/Azure/co-op-translator). למרות שאנו שואפים לדיוק, יש לקחת בחשבון שתרגומים אוטומטיים עשויים להכיל שגיאות או אי דיוקים. המסמך המקורי בשפתו המקורית צריך להיחשב כמקור סמכותי. עבור מידע קריטי, מומלץ להשתמש בתרגום מקצועי על ידי אדם. איננו נושאים באחריות לאי הבנות או לפרשנויות שגויות הנובעות משימוש בתרגום זה. \ No newline at end of file diff --git a/translations/hi/7-bank-project/4-state-management/README.md b/translations/hi/7-bank-project/4-state-management/README.md index 1069dc0f1..502c78f8a 100644 --- a/translations/hi/7-bank-project/4-state-management/README.md +++ b/translations/hi/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# 建立銀行應用程式第 4 部分:狀態管理的概念 +# 建立銀行應用程式第4部分:狀態管理概念 ## 課前測驗 @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### 簡介 -隨著網頁應用程式的規模增長,追蹤所有數據流變得越來越困難。哪些程式碼獲取數據,哪些頁面使用數據,數據需要在何時何地更新……很容易導致程式碼變得混亂且難以維護。當需要在應用程式的不同頁面之間共享數據時(例如用戶數據),這種情況尤其明顯。*狀態管理* 的概念一直存在於各類程式中,但隨著網頁應用程式的複雜性不斷增加,這已成為開發過程中需要重點考慮的問題。 +隨著網頁應用程式的規模增大,追蹤所有數據流變得越來越困難。哪些程式碼獲取數據,哪些頁面使用數據,數據需要在何時何地更新……很容易導致程式碼混亂且難以維護。尤其是當需要在應用程式的不同頁面之間共享數據時,例如用戶數據。*狀態管理*的概念一直存在於各類程式中,但隨著網頁應用程式的複雜性不斷增加,狀態管理已成為開發過程中的關鍵點。 -在這最後一部分,我們將重新審視我們建立的應用程式,重新思考如何管理狀態,從而支持瀏覽器隨時刷新,並在用戶會話之間持續保存數據。 +在這最後一部分,我們將重新審視我們建立的應用程式,重新思考如何管理狀態,以支持瀏覽器在任何時候刷新,並在用戶會話之間持續保存數據。 -### 先決條件 +### 前置條件 -在學習本課之前,您需要完成網頁應用程式的 [數據獲取](../3-data/README.md) 部分。此外,您需要安裝 [Node.js](https://nodejs.org) 並在本地 [運行伺服器 API](../api/README.md),以便管理帳戶數據。 +您需要完成本課程的網頁應用程式的[數據獲取](../3-data/README.md)部分。此外,您需要安裝 [Node.js](https://nodejs.org) 並[在本地運行伺服器 API](../api/README.md),以便管理帳戶數據。 您可以通過在終端執行以下命令來測試伺服器是否正常運行: @@ -34,34 +34,34 @@ curl http://localhost:5000/api ## 重新思考狀態管理 -在[上一課](../3-data/README.md)中,我們在應用程式中引入了一個基本的狀態概念,使用全域變數 `account` 來存儲當前登錄用戶的銀行數據。然而,我們目前的實現存在一些缺陷。嘗試在儀表板頁面刷新頁面,會發生什麼? +在[上一課](../3-data/README.md)中,我們在應用程式中引入了一個基本的狀態概念,即全局變數 `account`,它包含當前登錄用戶的銀行數據。然而,我們目前的實現存在一些缺陷。嘗試在儀表板頁面刷新瀏覽器。會發生什麼? -目前的程式碼有三個問題: +目前程式碼有三個問題: -- 狀態未被持久化,刷新瀏覽器會將您帶回登錄頁面。 -- 有多個函數修改狀態。隨著應用程式的增長,這會使得追蹤更改變得困難,並且容易忘記更新某些部分。 -- 狀態未被清理,因此當您點擊 *登出* 時,即使您已經回到登錄頁面,帳戶數據仍然存在。 +- 狀態未持久化,瀏覽器刷新會將您帶回登錄頁面。 +- 有多個函數修改狀態。隨著應用程式的增長,這可能使追蹤更改變得困難,並且容易忘記更新某些部分。 +- 狀態未清理,因此當您點擊*登出*時,帳戶數據仍然存在,即使您已回到登錄頁面。 -我們可以逐一更新程式碼來解決這些問題,但這會導致程式碼重複,並使應用程式更加複雜且難以維護。或者,我們可以暫停幾分鐘,重新思考我們的策略。 +我們可以逐一更新程式碼以解決這些問題,但這會導致程式碼重複並使應用程式更加複雜且難以維護。或者,我們可以暫停幾分鐘,重新思考我們的策略。 -> 我們真正想解決的問題是什麼? +> 我們真正想要解決的問題是什麼? -[狀態管理](https://en.wikipedia.org/wiki/State_management) 的核心在於找到一個好的方法來解決以下兩個特定問題: +[狀態管理](https://en.wikipedia.org/wiki/State_management)的核心在於找到一個良好的方法來解決以下兩個特定問題: -- 如何讓應用程式中的數據流保持清晰易懂? +- 如何使應用程式中的數據流易於理解? - 如何確保狀態數據始終與用戶界面保持同步(反之亦然)? -一旦解決了這些問題,您可能面臨的其他問題要麼已經被解決,要麼變得更容易解決。有許多方法可以解決這些問題,但我們將採用一種常見的解決方案,即 **集中化數據及其更改方式**。數據流將如下所示: +一旦解決了這些問題,您可能面臨的其他問題要麼已經解決,要麼變得更容易解決。有許多可能的方法可以解決這些問題,但我們將採用一種常見的解決方案,即**集中化數據及其更改方式**。數據流將如下所示: -![顯示 HTML、用戶操作和狀態之間數據流的圖表](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.hk.png) +![顯示 HTML、用戶操作和狀態之間數據流的示意圖](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.hk.png) -> 我們不會在此處討論數據自動觸發視圖更新的部分,因為這涉及到更高級的 [反應式編程](https://en.wikipedia.org/wiki/Reactive_programming) 概念。如果您有興趣深入研究,這是一個不錯的後續主題。 +> 我們在此不會涵蓋數據自動觸發視圖更新的部分,因為它涉及到更高級的[反應式編程](https://en.wikipedia.org/wiki/Reactive_programming)概念。如果您有興趣深入研究,這是一個不錯的後續主題。 -✅ 市面上有許多不同方法的狀態管理庫,[Redux](https://redux.js.org) 是一個受歡迎的選擇。了解其概念和模式通常是學習大型網頁應用程式中可能面臨的問題及其解決方法的好途徑。 +✅ 市面上有許多不同方法的狀態管理庫,[Redux](https://redux.js.org) 是一個流行的選擇。了解其使用的概念和模式通常是一個很好的方式,可以幫助您了解在大型網頁應用程式中可能面臨的問題以及如何解決。 ### 任務 -我們將從一些重構開始。將 `account` 的宣告替換為: +我們將從一些重構開始。替換 `account` 的聲明: ```js let account = null; @@ -75,11 +75,11 @@ let state = { }; ``` -這個想法是將我們應用程式的所有數據集中到一個單一的狀態物件中。目前狀態中只有 `account`,因此變化不大,但這為未來的擴展鋪平了道路。 +這個想法是將我們的應用程式數據*集中化*到一個單一的狀態對象中。目前狀態中只有 `account`,因此變化不大,但這為未來的擴展奠定了基礎。 -我們還需要更新使用它的函數。在 `register()` 和 `login()` 函數中,將 `account = ...` 替換為 `state.account = ...`。 +我們還需要更新使用它的函數。在 `register()` 和 `login()` 函數中,將 `account = ...` 替換為 `state.account = ...`; -在 `updateDashboard()` 函數的頂部,添加以下程式碼: +在 `updateDashboard()` 函數的頂部,添加以下行: ```js const account = state.account; @@ -87,15 +87,15 @@ const account = state.account; 這次重構本身並未帶來太多改進,但其目的是為接下來的更改奠定基礎。 -## 追蹤數據變更 +## 追蹤數據更改 -現在我們已經設置了用於存儲數據的 `state` 物件,下一步是集中更新。目標是讓追蹤任何變更及其發生時間變得更容易。 +現在我們已經設置了 `state` 對象來存儲數據,下一步是集中更新。目的是使追蹤任何更改及其發生時間變得更容易。 -為了避免對 `state` 物件進行更改,將其視為 [*不可變*](https://en.wikipedia.org/wiki/Immutable_object) 是一個好習慣,這意味著它完全不能被修改。這也意味著如果您想更改其中的任何內容,必須創建一個新的狀態物件。通過這樣做,您可以防止潛在的 [副作用](https://en.wikipedia.org/wiki/Side_effect_(computer_science)),並為應用程式的新功能(例如實現撤銷/重做)打開可能性,同時也更容易進行除錯。例如,您可以記錄對狀態所做的每次更改,並保留更改歷史以了解錯誤的來源。 +為了避免對 `state` 對象進行更改,將其視為[*不可變*](https://en.wikipedia.org/wiki/Immutable_object)是一個良好的做法,這意味著它完全不能被修改。這也意味著如果您想更改其中的任何內容,必須創建一個新的狀態對象。通過這樣做,您可以防止潛在的[副作用](https://en.wikipedia.org/wiki/Side_effect_(computer_science)),並為應用程式的新功能(例如實現撤銷/重做)打開可能性,同時使調試更容易。例如,您可以記錄對狀態所做的每次更改,並保留更改的歷史記錄,以了解錯誤的來源。 -在 JavaScript 中,您可以使用 [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) 創建物件的不可變版本。如果您嘗試更改不可變物件,將會引發異常。 +在 JavaScript 中,您可以使用 [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) 創建對象的不可變版本。如果嘗試更改不可變對象,將引發異常。 -✅ 您知道 *淺層* 和 *深層* 不可變物件之間的區別嗎?您可以在[這裡](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze)閱讀相關內容。 +✅ 您知道*淺層*和*深層*不可變對象的區別嗎?您可以在[這裡](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze)閱讀相關內容。 ### 任務 @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -在這個函數中,我們創建了一個新的狀態物件,並使用 [*展開運算符 (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) 從先前的狀態中複製數據。然後,我們使用 [方括號表示法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` 覆蓋狀態物件的特定屬性,並使用 `Object.freeze()` 鎖定物件以防止修改。目前狀態中僅存儲了 `account` 屬性,但通過這種方法,您可以在狀態中添加任意多的屬性。 +在此函數中,我們創建了一個新的狀態對象,並使用[*展開運算符 (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals)從之前的狀態中複製數據。然後,我們使用[方括號表示法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` 覆蓋狀態對象的特定屬性。最後,我們使用 `Object.freeze()` 鎖定對象以防止修改。目前狀態中僅存儲 `account` 屬性,但使用此方法,您可以在狀態中添加任意多的屬性。 -我們還需要更新 `state` 的初始化,確保初始狀態也被凍結: +我們還需要更新 `state` 的初始化,以確保初始狀態也是不可變的: ```js let state = Object.freeze({ @@ -126,15 +126,15 @@ let state = Object.freeze({ updateState('account', result); ``` -對 `login` 函數執行相同操作,將 `state.account = data;` 替換為: +對 `login` 函數進行相同的操作,將 `state.account = data;` 替換為: ```js updateState('account', data); ``` -現在我們可以順便解決用戶點擊 *登出* 時帳戶數據未被清除的問題。 +現在我們可以趁機修復用戶點擊*登出*時帳戶數據未清除的問題。 -創建一個新函數 `logout()`: +創建一個新的函數 `logout()`: ```js function logout() { @@ -143,49 +143,49 @@ function logout() { } ``` -在 `updateDashboard()` 中,將重定向 `return navigate('/login');` 替換為 `return logout();`。 +在 `updateDashboard()` 中,將重定向 `return navigate('/login');` 替換為 `return logout();`; -嘗試註冊一個新帳戶,登出並重新登錄,檢查一切是否仍然正常運作。 +嘗試註冊新帳戶,登出並再次登錄,檢查是否一切正常。 -> 提示:您可以在 `updateState()` 的底部添加 `console.log(state)`,然後打開瀏覽器開發工具中的控制台,查看所有狀態變更。 +> 提示:您可以通過在 `updateState()` 的底部添加 `console.log(state)` 並打開瀏覽器的開發工具中的控制台來查看所有狀態更改。 ## 持久化狀態 -大多數網頁應用程式需要持久化數據才能正常運作。所有關鍵數據通常存儲在數據庫中,並通過伺服器 API 訪問,例如我們的用戶帳戶數據。但有時,將某些數據持久化到運行於瀏覽器中的客戶端應用程式中也是有意義的,這樣可以提升用戶體驗或改善加載性能。 +大多數網頁應用程式需要持久化數據才能正常工作。所有關鍵數據通常存儲在數據庫中,並通過伺服器 API 訪問,例如我們的用戶帳戶數據。但有時,將某些數據存儲在瀏覽器中運行的客戶端應用程式中也是有益的,這可以改善用戶體驗或提高加載性能。 -當您想在瀏覽器中持久化數據時,有幾個重要問題需要考慮: +當您想在瀏覽器中持久化數據時,有幾個重要問題需要問自己: - *數據是否敏感?* 您應避免在客戶端存儲任何敏感數據,例如用戶密碼。 -- *需要保存這些數據多久?* 您是只打算在當前會話中訪問這些數據,還是希望永久保存? +- *您需要保存這些數據多久?* 您是僅在當前會話中訪問這些數據,還是希望永久保存? -根據您的需求,有多種方法可以在網頁應用程式中存儲信息。例如,您可以使用 URL 存儲搜索查詢,並使其可在用戶之間共享。您還可以使用 [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) 存儲需要與伺服器共享的數據,例如 [身份驗證](https://en.wikipedia.org/wiki/Authentication) 信息。 +根據您的需求,有多種方法可以在網頁應用程式中存儲信息。例如,您可以使用 URL 存儲搜索查詢,並使其可在用戶之間共享。您還可以使用[HTTP Cookie](https://developer.mozilla.org/docs/Web/HTTP/Cookies) 如果需要與伺服器共享數據,例如[身份驗證](https://en.wikipedia.org/wiki/Authentication)信息。 -另一個選項是使用多種瀏覽器 API 之一來存儲數據。其中兩個特別有趣: +另一個選擇是使用瀏覽器提供的多種存儲數據的 API,其中有兩個特別值得注意: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):一個 [鍵值存儲](https://en.wikipedia.org/wiki/Key%E2%80%93value_database),允許在不同會話中持久化特定於當前網站的數據。存儲在其中的數據永不過期。 -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):其工作方式與 `localStorage` 相同,但存儲在其中的數據會在會話結束(瀏覽器關閉時)被清除。 +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):一個[鍵值存儲](https://en.wikipedia.org/wiki/Key%E2%80%93value_database),允許跨不同會話持久化特定於當前網站的數據。存儲在其中的數據永不過期。 +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):其工作方式與 `localStorage` 相同,但存儲在其中的數據在會話結束(瀏覽器關閉時)時會被清除。 -請注意,這兩個 API 僅允許存儲 [字串](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) 格式。 +請注意,這兩個 API 只允許存儲[字符串](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) 在客戶端創建數據庫。這適用於高級用例或需要存儲大量數據的情況,因為它的使用更為複雜。 +✅ 如果您想創建一個不依賴伺服器的網頁應用程式,也可以使用 [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) 在客戶端創建數據庫。這適用於高級用例或需要存儲大量數據的情況,因為它使用起來更為複雜。 ### 任務 -我們希望用戶在明確點擊 *登出* 按鈕之前保持登錄狀態,因此我們將使用 `localStorage` 存儲帳戶數據。首先,定義一個用於存儲數據的鍵。 +我們希望用戶在明確點擊*登出*按鈕之前保持登錄狀態,因此我們將使用 `localStorage` 存儲帳戶數據。首先,定義一個用於存儲數據的鍵。 ```js const storageKey = 'savedAccount'; ``` -然後在 `updateState()` 函數的末尾添加以下程式碼: +然後在 `updateState()` 函數的末尾添加以下行: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -通過這樣做,用戶帳戶數據將被持久化,並且由於我們之前集中化了所有狀態更新,因此數據始終是最新的。這正是我們之前重構的好處 🙂。 +通過這樣做,用戶帳戶數據將被持久化並始終保持最新,因為我們之前已集中化了所有狀態更新。這是我們開始從之前的所有重構中受益的地方 🙂。 -由於數據已被保存,我們還需要在應用程式加載時恢復它。由於我們將開始有更多的初始化程式碼,因此創建一個新的 `init` 函數可能是個好主意,並將其包含在 `app.js` 的底部: +由於數據已保存,我們還需要在應用程式加載時恢復它。由於我們將開始擁有更多初始化程式碼,因此創建一個新的 `init` 函數可能是一個好主意,該函數還包括之前在 `app.js` 底部的程式碼: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -在這裡,我們檢索保存的數據,如果有數據,則相應地更新狀態。重要的是要在更新路由 *之前* 執行此操作,因為在頁面更新期間可能有程式碼依賴於狀態。 +在此,我們檢索保存的數據,如果有任何數據,我們會相應地更新狀態。重要的是在更新路由*之前*執行此操作,因為在頁面更新期間可能有程式碼依賴於狀態。 -我們還可以將 *儀表板* 頁設為應用程式的默認頁面,因為我們現在已經持久化了帳戶數據。如果未找到數據,儀表板會負責重定向到 *登錄* 頁。在 `updateRoute()` 中,將回退的 `return navigate('/login');` 替換為 `return navigate('/dashboard');`。 +我們還可以將*儀表板*頁設為應用程式的默認頁面,因為我們現在正在持久化帳戶數據。如果未找到數據,儀表板會負責重定向到*登錄*頁面。在 `updateRoute()` 中,將回退 `return navigate('/login');` 替換為 `return navigate('/dashboard');`。 -現在登錄應用程式並嘗試刷新頁面。您應該仍然停留在儀表板頁面。通過這次更新,我們解決了所有初始問題…… +現在登錄應用程式並嘗試刷新頁面。您應該停留在儀表板頁面。通過此更新,我們已解決所有初始問題... ## 刷新數據 -……但我們可能也創造了一個新問題。糟糕! +...但我們可能也創造了一個新問題。糟糕! -使用 `test` 帳戶進入儀表板,然後在終端運行以下命令創建一個新交易: +使用 `test` 帳戶進入儀表板,然後在終端運行以下命令以創建新交易: ```sh curl --request POST \ @@ -221,15 +221,15 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -現在嘗試在瀏覽器中刷新儀表板頁面。會發生什麼?您是否看到新交易? +現在嘗試在瀏覽器中刷新儀表板頁面。會發生什麼?您是否看到新的交易? -由於 `localStorage` 的狀態被無限期持久化,這也意味著它在您登出應用程式並重新登錄之前永遠不會更新! +由於 `localStorage` 的狀態被無限期持久化,但這也意味著在您登出應用程式並再次登錄之前,它永遠不會更新! -解決此問題的一種可能策略是每次加載儀表板時重新加載帳戶數據,以避免數據陳舊。 +解決此問題的一種可能策略是每次加載儀表板時重新加載帳戶數據,以避免數據過時。 ### 任務 -創建一個新函數 `updateAccountData`: +創建一個新的函數 `updateAccountData`: ```js async function updateAccountData() { @@ -249,7 +249,7 @@ async function updateAccountData() { 此方法檢查我們當前是否已登錄,然後從伺服器重新加載帳戶數據。 -再創建另一個名為 `refresh` 的函數: +創建另一個名為 `refresh` 的函數: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -此函數更新帳戶數據,然後負責更新儀表板頁面的 HTML。這是我們需要在加載儀表板路由時調用的函數。使用以下程式碼更新路由定義: +此函數更新帳戶數據,然後負責更新儀表板頁面的 HTML。這是我們需要在儀表板路由加載時調用的函數。使用以下程式碼更新路由定義: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -現在嘗試重新加載儀表板,它應該顯示更新的帳戶數據。 +現在嘗試刷新儀表板,它應顯示更新的帳戶數據。 --- ## 🚀 挑戰 -現在我們每次加載儀表板時都會重新加載帳戶數據,您認為我們是否仍然需要持久化 *所有帳戶* 數據? +現在我們每次加載儀表板時都會重新加載帳戶數據,您認為我們是否仍然需要持久化*所有帳戶*數據? -嘗試一起修改 `localStorage` 中保存和加載的內容,只包括應用程式正常運作所需的數據。 +嘗試一起合作更改 `localStorage` 中保存和加載的內容,以僅包含應用程式正常運行所需的絕對必要數據。 ## 課後測驗 - [課後測驗](https://ff-quizzes.netlify.app/web/quiz/48) ## 作業 + [實現「新增交易」對話框](assignment.md) -以下是一個完成任務後的範例結果: +以下是完成作業後的範例結果: -![顯示「新增交易」對話框範例的截圖](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.hk.png) +![截圖顯示範例「新增交易」對話框](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.hk.png) --- **免責聲明**: -此文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解讀概不負責。 \ No newline at end of file +本文件已使用人工智能翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於重要信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或錯誤解釋概不負責。 \ No newline at end of file diff --git a/translations/hr/7-bank-project/4-state-management/README.md b/translations/hr/7-bank-project/4-state-management/README.md index 3260fed07..d8230fc86 100644 --- a/translations/hr/7-bank-project/4-state-management/README.md +++ b/translations/hr/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Banki alkalmazás építése 4. rész: Állapotkezelés fogalmai +# Banki alkalmazás készítése 4. rész: Az állapotkezelés alapjai ## Előadás előtti kvíz @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Bevezetés -Ahogy egy webalkalmazás növekszik, egyre nehezebb nyomon követni az összes adatáramlást. Melyik kód kapja meg az adatokat, melyik oldal használja fel, hol és mikor kell frissíteni... könnyen előfordulhat, hogy rendezetlen kódot kapunk, amelyet nehéz karbantartani. Ez különösen igaz, ha az adatokat meg kell osztani az alkalmazás különböző oldalai között, például a felhasználói adatokat. Az *állapotkezelés* fogalma mindig is létezett mindenféle programban, de ahogy a webalkalmazások egyre bonyolultabbá válnak, ez ma már kulcsfontosságú szempont a fejlesztés során. +Ahogy egy webalkalmazás növekszik, egyre nehezebb nyomon követni az összes adatáramlást. Melyik kód kapja meg az adatokat, melyik oldal használja fel, hol és mikor kell frissíteni... könnyen előfordulhat, hogy a kód rendezetlenné válik, és nehéz karbantartani. Ez különösen igaz, ha az adatokat meg kell osztani az alkalmazás különböző oldalai között, például a felhasználói adatokat. Az *állapotkezelés* fogalma mindig is létezett mindenféle programban, de ahogy a webalkalmazások egyre összetettebbé válnak, ez ma már kulcsfontosságú szempont a fejlesztés során. -Ebben az utolsó részben átnézzük az általunk épített alkalmazást, hogy újragondoljuk az állapotkezelést, lehetővé téve a böngésző frissítését bármikor, és az adatok megőrzését a felhasználói munkamenetek között. +Ebben az utolsó részben áttekintjük az eddig elkészített alkalmazást, hogy újragondoljuk az állapot kezelését, lehetővé téve a böngésző frissítését bármely ponton, és az adatok megőrzését a felhasználói munkamenetek között. ### Előfeltétel -A webalkalmazás [adatlekérés](../3-data/README.md) részét be kell fejezned ehhez a leckéhez. Továbbá telepítened kell a [Node.js](https://nodejs.org) programot, és [helyileg futtatnod kell a szerver API-t](../api/README.md), hogy kezelni tudd a fiókadatokat. +A [adatlekérés](../3-data/README.md) részét már el kell végezned az alkalmazásnak ehhez a leckéhez. Továbbá telepítened kell a [Node.js](https://nodejs.org) programot, és [helyileg futtatnod kell a szerver API-t](../api/README.md), hogy kezelni tudd a fiókadatokat. Ellenőrizheted, hogy a szerver megfelelően fut-e, ha végrehajtod ezt a parancsot egy terminálban: @@ -32,32 +32,32 @@ curl http://localhost:5000/api --- -## Állapotkezelés újragondolása +## Az állapotkezelés újragondolása -Az [előző leckében](../3-data/README.md) bevezettük az állapot alapfogalmát az alkalmazásunkban a globális `account` változóval, amely tartalmazza az aktuálisan bejelentkezett felhasználó banki adatait. Azonban a jelenlegi megvalósításunknak vannak hiányosságai. Próbáld meg frissíteni az oldalt, amikor a vezérlőpulton vagy. Mi történik? +Az [előző leckében](../3-data/README.md) bevezettük az állapot alapfogalmát az alkalmazásunkban a globális `account` változóval, amely tartalmazza az aktuálisan bejelentkezett felhasználó banki adatait. Azonban a jelenlegi megvalósításunknak vannak hibái. Próbáld meg frissíteni az oldalt, amikor a műszerfalon vagy. Mi történik? A jelenlegi kóddal három probléma van: - Az állapot nem marad meg, mivel a böngésző frissítése visszavisz a bejelentkezési oldalra. -- Több funkció módosítja az állapotot. Ahogy az alkalmazás növekszik, nehéz lehet nyomon követni a változásokat, és könnyen elfelejthetünk frissíteni egyet. +- Több funkció módosítja az állapotot. Ahogy az alkalmazás növekszik, nehéz lehet nyomon követni a változásokat, és könnyű elfelejteni egy frissítést. - Az állapot nincs megtisztítva, így amikor a *Kijelentkezés* gombra kattintasz, a fiókadatok még mindig ott vannak, annak ellenére, hogy a bejelentkezési oldalon vagy. Frissíthetnénk a kódunkat, hogy egyenként kezeljük ezeket a problémákat, de ez több kódismétlést eredményezne, és az alkalmazás bonyolultabbá és nehezebben karbantarthatóvá válna. Vagy megállhatnánk néhány percre, és újragondolhatnánk a stratégiánkat. > Milyen problémákat próbálunk valójában megoldani? -Az [állapotkezelés](https://en.wikipedia.org/wiki/State_management) lényege, hogy jó megközelítést találjunk ennek a két konkrét problémának a megoldására: +Az [állapotkezelés](https://en.wikipedia.org/wiki/State_management) lényege, hogy jó megközelítést találjunk e két konkrét probléma megoldására: - Hogyan lehet az adatáramlásokat egy alkalmazásban érthetővé tenni? - Hogyan lehet az állapotadatokat mindig szinkronban tartani a felhasználói felülettel (és fordítva)? -Ha ezeket megoldottad, bármilyen más probléma, amivel szembesülhetsz, vagy már megoldódott, vagy könnyebben megoldhatóvá vált. Számos lehetséges megközelítés létezik ezeknek a problémáknak a megoldására, de mi egy gyakori megoldást választunk, amely **az adatok és a módosítási lehetőségek központosítását** foglalja magában. Az adatáramlás így nézne ki: +Ha ezeket megoldottad, bármely más probléma, amellyel szembesülhetsz, vagy már megoldódott, vagy könnyebben megoldhatóvá vált. Számos lehetséges megközelítés létezik ezeknek a problémáknak a megoldására, de mi egy gyakori megoldást választunk, amely abból áll, hogy **központosítjuk az adatokat és a módokat, ahogyan azokat megváltoztatjuk**. Az adatáramlások így néznének ki: -![Séma az adatáramlásról a HTML, a felhasználói műveletek és az állapot között](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.hu.png) +![Séma, amely bemutatja az adatáramlást a HTML, a felhasználói műveletek és az állapot között](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.hu.png) -> Itt nem térünk ki arra a részre, ahol az adatok automatikusan frissítik a nézetet, mivel ez a [Reaktív programozás](https://en.wikipedia.org/wiki/Reactive_programming) fejlettebb fogalmaihoz kapcsolódik. Ez egy jó következő téma, ha mélyebben szeretnél belemerülni. +> Itt nem térünk ki arra a részre, ahol az adatok automatikusan frissítik a nézetet, mivel ez összefügg a [Reaktív programozás](https://en.wikipedia.org/wiki/Reactive_programming) fejlettebb fogalmaival. Ez egy jó következő téma, ha mélyebben szeretnél elmerülni. -✅ Számos könyvtár létezik különböző megközelítésekkel az állapotkezeléshez, például a [Redux](https://redux.js.org), amely egy népszerű opció. Nézd meg a használt fogalmakat és mintákat, mivel gyakran jó módja annak, hogy megtudd, milyen potenciális problémákkal szembesülhetsz nagy webalkalmazásokban, és hogyan lehet ezeket megoldani. +✅ Számos könyvtár létezik különböző megközelítésekkel az állapotkezelésre, például a [Redux](https://redux.js.org), amely egy népszerű opció. Nézd meg a használt fogalmakat és mintákat, mivel gyakran jó módja annak, hogy megtudd, milyen potenciális problémákkal szembesülhetsz nagy webalkalmazásokban, és hogyan lehet ezeket megoldani. ### Feladat @@ -67,7 +67,7 @@ Kezdjünk egy kis refaktorálással. Cseréld le az `account` deklarációt: let account = null; ``` -Erre: +Ezzel: ```js let state = { @@ -77,7 +77,7 @@ let state = { Az ötlet az, hogy *központosítsuk* az összes alkalmazásadatot egyetlen állapotobjektumban. Jelenleg csak az `account` van az állapotban, így ez nem változtat sokat, de megnyitja az utat a további fejlesztések előtt. -Frissítenünk kell az ezt használó funkciókat is. A `register()` és `login()` funkciókban cseréld le az `account = ...` kifejezést `state.account = ...`-ra; +Frissítenünk kell az azt használó funkciókat is. A `register()` és `login()` funkciókban cseréld le az `account = ...` kifejezést `state.account = ...`-ra. Az `updateDashboard()` funkció elején add hozzá ezt a sort: @@ -87,13 +87,13 @@ const account = state.account; Ez a refaktorálás önmagában nem hozott sok javulást, de az ötlet az volt, hogy lefektessük az alapokat a következő változtatásokhoz. -## Adatváltozások nyomon követése +## Az adatváltozások nyomon követése -Most, hogy létrehoztuk az `state` objektumot az adataink tárolására, a következő lépés az, hogy központosítsuk a frissítéseket. A cél az, hogy könnyebb legyen nyomon követni a változásokat és azt, hogy mikor történnek. +Most, hogy létrehoztuk a `state` objektumot az adataink tárolására, a következő lépés az, hogy központosítsuk a frissítéseket. A cél az, hogy könnyebb legyen nyomon követni a változásokat és azt, hogy mikor történnek. -Az `state` objektum módosításának elkerülése érdekében jó gyakorlatnak számít, ha azt [*változtathatatlannak*](https://en.wikipedia.org/wiki/Immutable_object) tekintjük, ami azt jelenti, hogy egyáltalán nem lehet módosítani. Ez azt is jelenti, hogy új állapotobjektumot kell létrehoznod, ha bármit meg akarsz változtatni benne. Ezzel védelmet építesz ki a potenciálisan nem kívánt [mellékhatások](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) ellen, és lehetőséget nyitsz új funkciók bevezetésére az alkalmazásodban, például visszavonás/újra végrehajtás implementálására, miközben megkönnyíted a hibakeresést. Például naplózhatnád az állapotban végrehajtott minden változást, és megőrizhetnéd a változások történetét, hogy megértsd egy hiba forrását. +Az is jó gyakorlat, ha az állapotobjektumot [*változtathatatlannak*](https://en.wikipedia.org/wiki/Immutable_object) tekintjük, ami azt jelenti, hogy egyáltalán nem módosítható. Ez azt is jelenti, hogy új állapotobjektumot kell létrehoznod, ha bármit meg akarsz változtatni benne. Ezzel védelmet építesz ki a potenciálisan nem kívánt [mellékhatások](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) ellen, és lehetőséget nyitsz új funkciók bevezetésére az alkalmazásodban, például az undo/redo megvalósítására, miközben megkönnyíted a hibakeresést. Például naplózhatnád az állapoton végrehajtott minden változást, és nyomon követhetnéd a változások történetét, hogy megértsd egy hiba forrását. -JavaScriptben az [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) segítségével hozhatsz létre egy változtathatatlan objektumot. Ha megpróbálsz változtatásokat végrehajtani egy változtathatatlan objektumon, kivétel keletkezik. +JavaScriptben az [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) segítségével hozhatsz létre egy változtathatatlan verziót egy objektumból. Ha megpróbálsz változtatásokat végrehajtani egy változtathatatlan objektumon, kivétel keletkezik. ✅ Tudod, mi a különbség a *sekély* és a *mély* változtathatatlan objektum között? Olvass róla [itt](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Ebben a funkcióban létrehozunk egy új állapotobjektumot, és az előző állapotból másoljuk az adatokat a [*spread (`...`) operátor*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) segítségével. Ezután felülírunk egy adott tulajdonságot az állapotobjektumban az új adatokkal a [zárójel notáció](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` használatával. Végül zároljuk az objektumot, hogy megakadályozzuk a módosításokat az `Object.freeze()` segítségével. Jelenleg csak az `account` tulajdonságot tároljuk az állapotban, de ezzel a megközelítéssel annyi tulajdonságot adhatsz hozzá az állapothoz, amennyire szükséged van. +Ebben a funkcióban létrehozunk egy új állapotobjektumot, és az előző állapotból másolunk adatokat a [*spread (`...`) operátor*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) segítségével. Ezután felülírunk egy adott tulajdonságot az állapotobjektumban az új adatokkal a [szögletes zárójel](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` használatával. Végül zároljuk az objektumot, hogy megakadályozzuk a módosításokat az `Object.freeze()` segítségével. Jelenleg csak az `account` tulajdonságot tároljuk az állapotban, de ezzel a megközelítéssel annyi tulajdonságot adhatsz hozzá az állapothoz, amennyire szükséged van. Frissítsük az `state` inicializálását is, hogy az inicializálási állapot is zárolva legyen: @@ -120,13 +120,13 @@ let state = Object.freeze({ }); ``` -Ezután frissítsük a `register` funkciót az `state.account = result;` kifejezés lecserélésével: +Ezután frissítsük a `register` funkciót azzal, hogy az `state.account = result;` hozzárendelést lecseréljük erre: ```js updateState('account', result); ``` -Ugyanezt tegyük a `login` funkcióval, cseréljük le az `state.account = data;` kifejezést: +Ugyanezt tegyük a `login` funkcióval, cseréljük le az `state.account = data;` kifejezést erre: ```js updateState('account', data); @@ -143,31 +143,31 @@ function logout() { } ``` -Az `updateDashboard()`-ban cseréld le az `return navigate('/login');` átirányítást `return logout();`-ra; +Az `updateDashboard()`-ban cseréld le az `return navigate('/login');` átirányítást erre: `return logout();` Próbálj meg regisztrálni egy új fiókot, kijelentkezni, majd újra bejelentkezni, hogy ellenőrizd, minden továbbra is megfelelően működik-e. -> Tipp: megnézheted az összes állapotváltozást, ha hozzáadod a `console.log(state)` kifejezést az `updateState()` aljára, és megnyitod a böngésződ fejlesztői eszközeinek konzolját. +> Tipp: az összes állapotváltozást megtekintheted, ha hozzáadod a `console.log(state)` kifejezést az `updateState()` aljára, és megnyitod a böngésződ fejlesztői eszközeinek konzolját. ## Az állapot megőrzése -A legtöbb webalkalmazásnak meg kell őriznie az adatokat, hogy megfelelően működjön. Az összes kritikus adatot általában egy adatbázisban tárolják, és egy szerver API-n keresztül érik el, például a felhasználói fiókadatokat esetünkben. De néha az is érdekes lehet, hogy az adatokat megőrizzük a böngészőben futó kliensalkalmazásban, a jobb felhasználói élmény vagy a betöltési teljesítmény javítása érdekében. +A legtöbb webalkalmazásnak szüksége van az adatok megőrzésére, hogy megfelelően működjön. Az összes kritikus adatot általában egy adatbázisban tárolják, és egy szerver API-n keresztül érik el, például a felhasználói fiókadatokat esetünkben. De néha az is érdekes lehet, hogy néhány adatot megőrizzünk a böngészőben futó kliensalkalmazásban, jobb felhasználói élmény vagy a betöltési teljesítmény javítása érdekében. Amikor adatokat szeretnél megőrizni a böngésződben, néhány fontos kérdést fel kell tenned magadnak: - *Érzékeny az adat?* Kerüld az érzékeny adatok, például a felhasználói jelszavak tárolását a kliensen. -- *Mennyi ideig szeretnéd megőrizni ezeket az adatokat?* Csak az aktuális munkamenet során szeretnéd elérni ezeket az adatokat, vagy örökre tárolni szeretnéd őket? +- *Mennyi ideig szeretnéd megőrizni ezeket az adatokat?* Csak az aktuális munkamenethez szeretnéd hozzáférni ezekhez az adatokhoz, vagy örökre tárolni szeretnéd őket? -Számos módja van az információk tárolásának egy webalkalmazásban, attól függően, hogy mit szeretnél elérni. Például használhatod az URL-eket egy keresési lekérdezés tárolására, és megoszthatod azt más felhasználókkal. Használhatsz [HTTP sütiket](https://developer.mozilla.org/docs/Web/HTTP/Cookies), ha az adatokat meg kell osztani a szerverrel, például az [azonosítási](https://en.wikipedia.org/wiki/Authentication) információkat. +Számos módja van az információk tárolásának egy webalkalmazásban, attól függően, hogy mit szeretnél elérni. Például használhatod az URL-eket egy keresési lekérdezés tárolására, és megoszthatod azt a felhasználók között. Használhatsz [HTTP sütiket](https://developer.mozilla.org/docs/Web/HTTP/Cookies), ha az adatokat meg kell osztani a szerverrel, például az [azonosítási](https://en.wikipedia.org/wiki/Authentication) információkat. -Egy másik lehetőség, hogy a böngésző API-k egyikét használod az adatok tárolására. Két különösen érdekes API létezik: +Egy másik lehetőség, hogy a böngésző API-k egyikét használod az adatok tárolására. Kettő különösen érdekes: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): egy [kulcs/érték tároló](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), amely lehetővé teszi az adott webhelyhez tartozó adatok megőrzését különböző munkamenetek között. Az itt tárolt adatok soha nem járnak le. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): egy [kulcs/érték tároló](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), amely lehetővé teszi az adott webhelyhez kapcsolódó adatok megőrzését különböző munkamenetek között. Az itt tárolt adatok soha nem járnak le. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ez ugyanúgy működik, mint a `localStorage`, kivéve, hogy az itt tárolt adatok törlődnek, amikor a munkamenet véget ér (amikor a böngészőt bezárják). -Fontos megjegyezni, hogy mindkét API csak [sztringeket](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) tud tárolni. Ha összetett objektumokat szeretnél tárolni, akkor azokat a [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) formátumba kell sorosítanod a [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) segítségével. +Fontos megjegyezni, hogy mindkét API csak [szövegeket](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) tud tárolni. Ha összetett objektumokat szeretnél tárolni, akkor azokat a [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) formátumba kell sorosítanod a [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) segítségével. -✅ Ha olyan webalkalmazást szeretnél létrehozni, amely nem működik szerverrel, akkor az [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) segítségével létrehozhatsz egy adatbázist a kliensen. Ez az opció fejlettebb esetekre vagy jelentős mennyiségű adat tárolására van fenntartva, mivel bonyolultabb a használata. +✅ Ha olyan webalkalmazást szeretnél létrehozni, amely nem működik szerverrel, akkor az ügyféloldalon is létrehozhatsz adatbázist az [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) segítségével. Ez az opció haladó felhasználási esetekre vagy jelentős mennyiségű adat tárolására van fenntartva, mivel bonyolultabb a használata. ### Feladat @@ -183,9 +183,9 @@ Ezután add hozzá ezt a sort az `updateState()` funkció végéhez: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Ezzel a felhasználói fiókadatok megmaradnak, és mindig naprakészek lesznek, mivel korábban központosítottuk az összes állapotfrissítést. Itt kezdjük el élvezni az összes korábbi refaktorálás előnyeit 🙂. +Ezzel a felhasználói fiókadatok megőrzésre kerülnek, és mindig naprakészek lesznek, mivel korábban központosítottuk az összes állapotfrissítést. Itt kezdjük el élvezni az összes korábbi refaktorálás előnyeit 🙂. -Mivel az adatok mentésre kerülnek, gondoskodnunk kell azok visszaállításáról is, amikor az alkalmazás betöltődik. Mivel egyre több inicializáló kódunk lesz, érdemes lehet létrehozni egy új `init` funkciót, amely tartalmazza a korábbi kódot is az `app.js` alján: +Mivel az adatok mentésre kerülnek, gondoskodnunk kell azok visszaállításáról is, amikor az alkalmazás betöltődik. Mivel egyre több inicializáló kódunk lesz, érdemes lehet létrehozni egy új `init` funkciót, amely magában foglalja a korábbi kódot is az `app.js` alján: ```js function init() { @@ -204,15 +204,15 @@ init(); Itt visszanyerjük a mentett adatokat, és ha van ilyen, frissítjük az állapotot ennek megfelelően. Fontos, hogy ezt *azelőtt* tegyük meg, hogy frissítenénk az útvonalat, mivel lehet, hogy van olyan kód, amely az állapotra támaszkodik az oldal frissítése során. -Az alkalmazás alapértelmezett oldalának is megtehetjük a *Vezérlőpult* oldalt, mivel most már megőrizzük a fiókadatokat. Ha nem található adat, a vezérlőpult gondoskodik arról, hogy átirányítson a *Bejelentkezés* oldalra. Az `updateRoute()`-ban cseréld le az alapértelmezett `return navigate('/login');` kifejezést `return navigate('/dashboard');`-ra. +Az alkalmazás alapértelmezett oldalának is megtehetjük a *Műszerfal* oldalt, mivel most már megőrizzük a fiókadatokat. Ha nem található adat, a műszerfal gondoskodik arról, hogy átirányítson a *Bejelentkezés* oldalra. Az `updateRoute()`-ban cseréld le az alapértelmezett `return navigate('/login');` kifejezést erre: `return navigate('/dashboard');`. -Most jelentkezz be az alkalmazásba, és próbáld meg frissíteni az oldalt. A vezérlőpulton kell maradnod. Ezzel a frissítéssel gondoskodtunk az összes kezdeti problémánkról... +Most jelentkezz be az alkalmazásba, és próbáld meg frissíteni az oldalt. A műszerfalon kell maradnod. Ezzel a frissítéssel gondoskodtunk az összes kezdeti problémánkról... ## Az adatok frissítése ...De lehet, hogy egy új problémát is létrehoztunk. Hoppá! -Menj a vezérlőpultra a `test` fiókkal, majd futtasd ezt a parancsot egy terminálban, hogy létrehozz egy új tranzakciót: +Menj a műszerfalra a `test` fiókkal, majd futtasd ezt a parancsot egy terminálban, hogy létrehozz egy új tranzakciót: ```sh curl --request POST \ @@ -221,16 +221,20 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Próbáld meg frissíteni a vezérlőpult oldalt a böngészőben. Mi történik? Látod az új tranzakciót? +Most próbáld meg frissíteni a műszerfal oldalát a böngészőben. Mi történik? Látod az új tranzakciót? -Az állapot határozatlan ideig megmarad a `localStorage`-nak köszönhetően, de ez azt is jelenti, hogy soha nem frissül, amíg ki nem jelentkezel az alkalmazásból, majd újra be -[Valósítsd meg a "Tranzakció hozzáadása" párbeszédablakot](assignment.md) +Az állapot határozatlan ideig megőrzésre kerül a `localStorage`-nak köszönhetően, de ez azt is jelenti, hogy soha nem frissül, amíg ki nem jelentkezel az alkalmazásból, majd újra be nem +[Előadás utáni kvíz](https://ff-quizzes.netlify.app/web/quiz/48) -Íme egy példakép az elkészült feladatról, amely bemutatja a "Tranzakció hozzáadása" párbeszédablakot: +## Feladat -![Képernyőkép, amely egy példát mutat a "Tranzakció hozzáadása" párbeszédablakra](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.hu.png) +[„Tranzakció hozzáadása” párbeszédablak megvalósítása](assignment.md) + +Íme egy példakép a feladat befejezése után: + +![Példa a „Tranzakció hozzáadása” párbeszédablakra](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.hu.png) --- -**Felelősségkizárás**: -Ezt a dokumentumot az [Co-op Translator](https://github.com/Azure/co-op-translator) AI fordítószolgáltatás segítségével fordítottuk le. Bár törekszünk a pontosságra, kérjük, vegye figyelembe, hogy az automatikus fordítások hibákat vagy pontatlanságokat tartalmazhatnak. Az eredeti dokumentum az eredeti nyelvén tekintendő hiteles forrásnak. Kritikus információk esetén javasolt a professzionális, emberi fordítás igénybevétele. Nem vállalunk felelősséget a fordítás használatából eredő félreértésekért vagy téves értelmezésekért. \ No newline at end of file +**Felelősség kizárása**: +Ez a dokumentum az [Co-op Translator](https://github.com/Azure/co-op-translator) AI fordítási szolgáltatás segítségével került lefordításra. Bár törekszünk a pontosságra, kérjük, vegye figyelembe, hogy az automatikus fordítások hibákat vagy pontatlanságokat tartalmazhatnak. Az eredeti dokumentum az eredeti nyelvén tekintendő hiteles forrásnak. Kritikus információk esetén javasolt professzionális emberi fordítást igénybe venni. Nem vállalunk felelősséget semmilyen félreértésért vagy téves értelmezésért, amely a fordítás használatából eredhet. \ No newline at end of file diff --git a/translations/id/7-bank-project/4-state-management/README.md b/translations/id/7-bank-project/4-state-management/README.md index 37e216cf2..97a7e884a 100644 --- a/translations/id/7-bank-project/4-state-management/README.md +++ b/translations/id/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Costruire un'App Bancaria Parte 4: Concetti di Gestione dello Stato +# Costruire un'app bancaria Parte 4: Concetti di gestione dello stato -## Quiz Pre-Lettura +## Quiz pre-lezione -[Quiz pre-lettura](https://ff-quizzes.netlify.app/web/quiz/47) +[Quiz pre-lezione](https://ff-quizzes.netlify.app/web/quiz/47) ### Introduzione -Man mano che un'applicazione web cresce, diventa una sfida tenere traccia di tutti i flussi di dati. Quale codice ottiene i dati, quale pagina li utilizza, dove e quando devono essere aggiornati... è facile finire con un codice disordinato e difficile da mantenere. Questo è particolarmente vero quando è necessario condividere dati tra diverse pagine della tua app, ad esempio i dati dell'utente. Il concetto di *gestione dello stato* è sempre esistito in tutti i tipi di programmi, ma con l'aumento della complessità delle app web è diventato un punto chiave da considerare durante lo sviluppo. +Man mano che un'applicazione web cresce, diventa una sfida tenere traccia di tutti i flussi di dati. Quale codice ottiene i dati, quale pagina li utilizza, dove e quando devono essere aggiornati... è facile finire con un codice disordinato e difficile da mantenere. Questo è particolarmente vero quando è necessario condividere dati tra diverse pagine della tua app, ad esempio i dati dell'utente. Il concetto di *gestione dello stato* è sempre esistito in tutti i tipi di programmi, ma poiché le app web continuano a crescere in complessità, ora è un punto chiave da considerare durante lo sviluppo. -In questa parte finale, esamineremo l'app che abbiamo costruito per ripensare a come viene gestito lo stato, consentendo il supporto per l'aggiornamento del browser in qualsiasi momento e la persistenza dei dati tra le sessioni utente. +In questa parte finale, esamineremo l'app che abbiamo costruito per ripensare a come viene gestito lo stato, consentendo il supporto per il refresh del browser in qualsiasi momento e la persistenza dei dati tra le sessioni utente. ### Prerequisiti -Devi aver completato la parte relativa al [recupero dei dati](../3-data/README.md) dell'app web per questa lezione. Inoltre, devi installare [Node.js](https://nodejs.org) e [eseguire l'API del server](../api/README.md) localmente per poter gestire i dati dell'account. +Devi aver completato la parte [data fetching](../3-data/README.md) dell'app web per questa lezione. Inoltre, devi installare [Node.js](https://nodejs.org) e [eseguire l'API del server](../api/README.md) localmente per gestire i dati dell'account. Puoi verificare che il server stia funzionando correttamente eseguendo questo comando in un terminale: @@ -34,30 +34,30 @@ curl http://localhost:5000/api ## Ripensare la gestione dello stato -Nella [lezione precedente](../3-data/README.md), abbiamo introdotto un concetto di base di stato nella nostra app con la variabile globale `account` che contiene i dati bancari dell'utente attualmente connesso. Tuttavia, la nostra implementazione attuale presenta alcune lacune. Prova ad aggiornare la pagina quando sei nella dashboard. Cosa succede? +Nella [lezione precedente](../3-data/README.md), abbiamo introdotto un concetto di base di stato nella nostra app con la variabile globale `account` che contiene i dati bancari dell'utente attualmente loggato. Tuttavia, la nostra implementazione attuale presenta alcune lacune. Prova a ricaricare la pagina quando sei sulla dashboard. Cosa succede? Ci sono 3 problemi con il codice attuale: -- Lo stato non è persistente, poiché un aggiornamento del browser ti riporta alla pagina di login. -- Ci sono più funzioni che modificano lo stato. Man mano che l'app cresce, può diventare difficile tenere traccia delle modifiche ed è facile dimenticare di aggiornare qualcosa. -- Lo stato non viene ripulito, quindi quando clicchi su *Logout* i dati dell'account sono ancora presenti anche se sei nella pagina di login. +- Lo stato non è persistente, poiché un refresh del browser ti riporta alla pagina di login. +- Ci sono molte funzioni che modificano lo stato. Man mano che l'app cresce, può diventare difficile tracciare i cambiamenti ed è facile dimenticare di aggiornare qualcosa. +- Lo stato non viene ripulito, quindi quando clicchi su *Logout* i dati dell'account sono ancora presenti anche se sei sulla pagina di login. Potremmo aggiornare il nostro codice per affrontare questi problemi uno per uno, ma ciò creerebbe più duplicazione di codice e renderebbe l'app più complessa e difficile da mantenere. Oppure potremmo fermarci per qualche minuto e ripensare la nostra strategia. -> Quali problemi stiamo davvero cercando di risolvere qui? +> Quali problemi stiamo cercando di risolvere qui? -La [gestione dello stato](https://en.wikipedia.org/wiki/State_management) riguarda il trovare un buon approccio per risolvere questi due problemi particolari: +La [gestione dello stato](https://en.wikipedia.org/wiki/State_management) riguarda principalmente il trovare un buon approccio per risolvere questi due problemi particolari: - Come mantenere i flussi di dati in un'app comprensibili? - Come mantenere i dati dello stato sempre sincronizzati con l'interfaccia utente (e viceversa)? -Una volta affrontati questi problemi, qualsiasi altra questione potrebbe essere già risolta o diventare più facile da risolvere. Esistono molti approcci possibili per affrontare questi problemi, ma utilizzeremo una soluzione comune che consiste nel **centralizzare i dati e i modi per modificarli**. I flussi di dati funzionerebbero così: +Una volta affrontati questi problemi, qualsiasi altro problema che potresti avere potrebbe essere già risolto o diventare più facile da risolvere. Esistono molti approcci possibili per risolvere questi problemi, ma utilizzeremo una soluzione comune che consiste nel **centralizzare i dati e i modi per modificarli**. I flussi di dati seguirebbero questo schema: ![Schema che mostra i flussi di dati tra l'HTML, le azioni dell'utente e lo stato](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.it.png) -> Qui non tratteremo la parte in cui i dati aggiornano automaticamente la vista, poiché è legata a concetti più avanzati di [Programmazione Reattiva](https://en.wikipedia.org/wiki/Reactive_programming). È un buon argomento di approfondimento se vuoi esplorare ulteriormente. +> Qui non tratteremo la parte in cui i dati aggiornano automaticamente la vista, poiché è legata a concetti più avanzati di [Programmazione Reattiva](https://en.wikipedia.org/wiki/Reactive_programming). È un buon argomento di approfondimento se sei interessato a un'immersione più profonda. -✅ Esistono molte librerie con approcci diversi alla gestione dello stato, [Redux](https://redux.js.org) essendo una delle opzioni più popolari. Dai un'occhiata ai concetti e ai pattern utilizzati, poiché spesso è un buon modo per imparare quali problemi potresti affrontare nelle grandi app web e come possono essere risolti. +✅ Esistono molte librerie con approcci diversi alla gestione dello stato, [Redux](https://redux.js.org) essendo una delle opzioni più popolari. Dai un'occhiata ai concetti e ai pattern utilizzati, poiché spesso è un buon modo per imparare quali problemi potresti affrontare in grandi app web e come possono essere risolti. ### Compito @@ -75,7 +75,7 @@ let state = { }; ``` -L'idea è di *centralizzare* tutti i dati della nostra app in un unico oggetto di stato. Per ora abbiamo solo `account` nello stato, quindi non cambia molto, ma crea una base per le evoluzioni future. +L'idea è di *centralizzare* tutti i dati della nostra app in un unico oggetto stato. Per ora abbiamo solo `account` nello stato, quindi non cambia molto, ma crea una base per evoluzioni future. Dobbiamo anche aggiornare le funzioni che lo utilizzano. Nelle funzioni `register()` e `login()`, sostituisci `account = ...` con `state.account = ...`; @@ -87,15 +87,15 @@ const account = state.account; Questo refactoring di per sé non ha portato grandi miglioramenti, ma l'idea era di gettare le basi per i prossimi cambiamenti. -## Tracciare le modifiche ai dati +## Tracciare i cambiamenti dei dati -Ora che abbiamo messo in atto l'oggetto `state` per memorizzare i nostri dati, il passo successivo è centralizzare gli aggiornamenti. L'obiettivo è rendere più facile tenere traccia di eventuali modifiche e quando avvengono. +Ora che abbiamo messo in atto l'oggetto `state` per memorizzare i nostri dati, il passo successivo è centralizzare gli aggiornamenti. L'obiettivo è rendere più facile tenere traccia di qualsiasi cambiamento e quando avviene. -Per evitare che vengano apportate modifiche all'oggetto `state`, è anche una buona pratica considerarlo [*immutabile*](https://en.wikipedia.org/wiki/Immutable_object), il che significa che non può essere modificato affatto. Significa anche che devi creare un nuovo oggetto di stato se vuoi cambiare qualcosa in esso. Facendo ciò, costruisci una protezione contro potenziali [effetti collaterali indesiderati](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) e apri possibilità per nuove funzionalità nella tua app, come implementare undo/redo, rendendo anche più facile il debug. Ad esempio, potresti registrare ogni modifica apportata allo stato e mantenere una cronologia delle modifiche per capire l'origine di un bug. +Per evitare che vengano apportate modifiche all'oggetto `state`, è anche una buona pratica considerarlo [*immutabile*](https://en.wikipedia.org/wiki/Immutable_object), il che significa che non può essere modificato affatto. Ciò significa anche che devi creare un nuovo oggetto stato se vuoi cambiare qualcosa in esso. Facendo così, costruisci una protezione contro potenziali [effetti collaterali](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) indesiderati e apri possibilità per nuove funzionalità nella tua app, come implementare undo/redo, rendendo anche più facile il debug. Ad esempio, potresti registrare ogni cambiamento fatto allo stato e mantenere una cronologia dei cambiamenti per capire la fonte di un bug. -In JavaScript, puoi utilizzare [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) per creare una versione immutabile di un oggetto. Se provi a modificare un oggetto immutabile, verrà generata un'eccezione. +In JavaScript, puoi usare [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) per creare una versione immutabile di un oggetto. Se provi a fare modifiche a un oggetto immutabile, verrà sollevata un'eccezione. -✅ Conosci la differenza tra un oggetto immutabile *superficiale* e uno *profondo*? Puoi leggerne di più [qui](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Conosci la differenza tra un oggetto immutabile *superficiale* e uno *profondo*? Puoi leggere a riguardo [qui](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Compito @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -In questa funzione, stiamo creando un nuovo oggetto di stato e copiando i dati dallo stato precedente utilizzando lo [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Poi sovrascriviamo una particolare proprietà dell'oggetto di stato con i nuovi dati utilizzando la [notazione a parentesi](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` per l'assegnazione. Infine, blocchiamo l'oggetto per impedire modifiche utilizzando `Object.freeze()`. Per ora abbiamo solo la proprietà `account` memorizzata nello stato, ma con questo approccio puoi aggiungere tutte le proprietà di cui hai bisogno. +In questa funzione, stiamo creando un nuovo oggetto stato e copiando i dati dallo stato precedente usando l'[operatore spread (`...`)](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Poi sovrascriviamo una particolare proprietà dell'oggetto stato con i nuovi dati usando la [notazione a parentesi](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` per l'assegnazione. Infine, blocchiamo l'oggetto per prevenire modifiche usando `Object.freeze()`. Per ora abbiamo solo la proprietà `account` memorizzata nello stato, ma con questo approccio puoi aggiungere tutte le proprietà di cui hai bisogno nello stato. -Aggiorneremo anche l'inizializzazione dello `state` per assicurarci che lo stato iniziale sia anch'esso bloccato: +Aggiorneremo anche l'inizializzazione dello stato per assicurarci che lo stato iniziale sia anch'esso bloccato: ```js let state = Object.freeze({ @@ -145,33 +145,33 @@ function logout() { In `updateDashboard()`, sostituisci il reindirizzamento `return navigate('/login');` con `return logout()`; -Prova a registrare un nuovo account, a fare logout e a rientrare per verificare che tutto funzioni ancora correttamente. +Prova a registrare un nuovo account, a disconnetterti e a riconnetterti per verificare che tutto funzioni correttamente. -> Suggerimento: puoi dare un'occhiata a tutte le modifiche dello stato aggiungendo `console.log(state)` alla fine di `updateState()` e aprendo la console negli strumenti di sviluppo del browser. +> Suggerimento: puoi dare un'occhiata a tutti i cambiamenti dello stato aggiungendo `console.log(state)` alla fine di `updateState()` e aprendo la console negli strumenti di sviluppo del tuo browser. ## Persistenza dello stato -La maggior parte delle app web ha bisogno di persistere i dati per funzionare correttamente. Tutti i dati critici sono solitamente memorizzati in un database e accessibili tramite un'API del server, come i dati dell'account utente nel nostro caso. Ma a volte, è anche interessante persistere alcuni dati nell'app client che gira nel browser, per migliorare l'esperienza utente o le prestazioni di caricamento. +La maggior parte delle app web ha bisogno di persistere i dati per funzionare correttamente. Tutti i dati critici sono solitamente memorizzati in un database e accessibili tramite un'API del server, come i dati dell'account utente nel nostro caso. Ma a volte, è anche interessante persistere alcuni dati nell'app client che gira nel tuo browser, per una migliore esperienza utente o per migliorare le prestazioni di caricamento. -Quando vuoi persistere i dati nel browser, ci sono alcune domande importanti che dovresti porti: +Quando vuoi persistere i dati nel tuo browser, ci sono alcune domande importanti che dovresti porti: - *I dati sono sensibili?* Dovresti evitare di memorizzare dati sensibili sul client, come le password degli utenti. -- *Per quanto tempo hai bisogno di conservare questi dati?* Vuoi accedere a questi dati solo per la sessione corrente o vuoi che siano memorizzati per sempre? +- *Per quanto tempo hai bisogno di conservare questi dati?* Intendi accedere a questi dati solo per la sessione corrente o vuoi che siano memorizzati per sempre? Esistono diversi modi per memorizzare informazioni all'interno di un'app web, a seconda di ciò che vuoi ottenere. Ad esempio, puoi utilizzare gli URL per memorizzare una query di ricerca e renderla condivisibile tra gli utenti. Puoi anche utilizzare i [cookie HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) se i dati devono essere condivisi con il server, come le informazioni di [autenticazione](https://en.wikipedia.org/wiki/Authentication). -Un'altra opzione è utilizzare una delle tante API del browser per memorizzare i dati. Due di esse sono particolarmente interessanti: +Un'altra opzione è utilizzare una delle molte API del browser per memorizzare i dati. Due di queste sono particolarmente interessanti: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): un [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) che consente di persistere i dati specifici del sito web corrente tra diverse sessioni. I dati salvati in esso non scadono mai. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): un [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) che consente di persistere dati specifici per il sito web corrente tra diverse sessioni. I dati salvati in esso non scadono mai. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funziona allo stesso modo di `localStorage` tranne per il fatto che i dati memorizzati in esso vengono cancellati quando la sessione termina (quando il browser viene chiuso). -Nota che entrambe queste API consentono solo di memorizzare [stringhe](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Se vuoi memorizzare oggetti complessi, dovrai serializzarli nel formato [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) utilizzando [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Nota che entrambe queste API consentono solo di memorizzare [stringhe](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Se vuoi memorizzare oggetti complessi, dovrai serializzarli nel formato [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) usando [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). ✅ Se vuoi creare un'app web che non funziona con un server, è anche possibile creare un database sul client utilizzando l'API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Questa è riservata a casi d'uso avanzati o se hai bisogno di memorizzare una quantità significativa di dati, poiché è più complessa da utilizzare. ### Compito -Vogliamo che i nostri utenti rimangano connessi fino a quando non cliccano esplicitamente sul pulsante *Logout*, quindi utilizzeremo `localStorage` per memorizzare i dati dell'account. Per prima cosa, definiamo una chiave che utilizzeremo per memorizzare i nostri dati. +Vogliamo che i nostri utenti rimangano loggati fino a quando non cliccano esplicitamente sul pulsante *Logout*, quindi utilizzeremo `localStorage` per memorizzare i dati dell'account. Per prima cosa, definiamo una chiave che utilizzeremo per memorizzare i nostri dati. ```js const storageKey = 'savedAccount'; @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); Con questo, i dati dell'account utente saranno persistenti e sempre aggiornati poiché abbiamo centralizzato in precedenza tutti gli aggiornamenti dello stato. È qui che iniziamo a beneficiare di tutti i nostri refactoring precedenti 🙂. -Poiché i dati vengono salvati, dobbiamo anche occuparci di ripristinarli quando l'app viene caricata. Poiché inizieremo ad avere più codice di inizializzazione, potrebbe essere una buona idea creare una nuova funzione `init`, che includa anche il nostro codice precedente in fondo a `app.js`: +Poiché i dati vengono salvati, dobbiamo anche occuparci di ripristinarli quando l'app viene caricata. Poiché inizieremo ad avere più codice di inizializzazione, potrebbe essere una buona idea creare una nuova funzione `init`, che includa anche il nostro codice precedente alla fine di `app.js`: ```js function init() { @@ -202,15 +202,15 @@ function init() { init(); ``` -Qui recuperiamo i dati salvati e, se presenti, aggiorniamo lo stato di conseguenza. È importante farlo *prima* di aggiornare la rotta, poiché potrebbe esserci del codice che si basa sullo stato durante l'aggiornamento della pagina. +Qui recuperiamo i dati salvati e, se ci sono, aggiorniamo lo stato di conseguenza. È importante farlo *prima* di aggiornare la rotta, poiché potrebbe esserci codice che si basa sullo stato durante l'aggiornamento della pagina. -Possiamo anche rendere la pagina *Dashboard* la pagina predefinita della nostra applicazione, poiché ora stiamo persistendo i dati dell'account. Se non vengono trovati dati, la dashboard si occupa di reindirizzare alla pagina di *Login* comunque. In `updateRoute()`, sostituisci il fallback `return navigate('/login');` con `return navigate('/dashboard');`. +Possiamo anche rendere la pagina *Dashboard* la pagina predefinita della nostra applicazione, poiché ora stiamo persistendo i dati dell'account. Se non vengono trovati dati, la dashboard si occupa di reindirizzare alla pagina *Login* comunque. In `updateRoute()`, sostituisci il fallback `return navigate('/login');` con `return navigate('/dashboard');`. -Ora accedi all'app e prova ad aggiornare la pagina. Dovresti rimanere sulla dashboard. Con questo aggiornamento abbiamo risolto tutti i nostri problemi iniziali... +Ora accedi all'app e prova a ricaricare la pagina. Dovresti rimanere sulla dashboard. Con questo aggiornamento abbiamo affrontato tutti i nostri problemi iniziali... ## Aggiornare i dati -...Ma potremmo anche averne creato uno nuovo. Ops! +...Ma potremmo anche averne creato uno nuovo. Oops! Vai alla dashboard utilizzando l'account `test`, quindi esegui questo comando su un terminale per creare una nuova transazione: @@ -221,7 +221,7 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Prova ad aggiornare la pagina della dashboard nel browser ora. Cosa succede? Vedi la nuova transazione? +Prova a ricaricare la pagina della dashboard nel browser ora. Cosa succede? Vedi la nuova transazione? Lo stato è persistente indefinitamente grazie a `localStorage`, ma ciò significa anche che non viene mai aggiornato fino a quando non esci dall'app e accedi di nuovo! @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Questo metodo verifica che siamo attualmente connessi, quindi ricarica i dati dell'account dal server. +Questo metodo verifica che siamo attualmente loggati e poi ricarica i dati dell'account dal server. Crea un'altra funzione chiamata `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Questa aggiorna i dati dell'account, quindi si occupa di aggiornare l'HTML della pagina della dashboard. È ciò che dobbiamo chiamare quando la rotta della dashboard viene caricata. Aggiorna la definizione della rotta con: +Questa funzione aggiorna i dati dell'account e poi si occupa di aggiornare l'HTML della pagina dashboard. È ciò che dobbiamo chiamare quando la rotta della dashboard viene caricata. Aggiorna la definizione della rotta con: ```js const routes = { @@ -267,7 +267,7 @@ const routes = { }; ``` -Prova ad aggiornare la dashboard ora, dovrebbe mostrare i dati dell'account aggiornati. +Prova a ricaricare la dashboard ora, dovrebbe mostrare i dati dell'account aggiornati. --- @@ -275,20 +275,20 @@ Prova ad aggiornare la dashboard ora, dovrebbe mostrare i dati dell'account aggi Ora che ricarichiamo i dati dell'account ogni volta che la dashboard viene caricata, pensi che sia ancora necessario persistere *tutti i dati dell'account*? -Prova a lavorare insieme per modificare ciò che viene salvato e caricato da `localStorage` per includere solo ciò che è assolutamente necessario per il funzionamento dell'app. +Prova a lavorare insieme per modificare ciò che viene salvato e caricato da `localStorage` includendo solo ciò che è assolutamente necessario per il funzionamento dell'app. -## Quiz Post-Lettura - -[Quiz post-lettura](https://ff-quizzes.netlify.app/web/quiz/48) +## Quiz post-lezione +[Quiz post-lezione](https://ff-quizzes.netlify.app/web/quiz/48) ## Compito -[Implementa la finestra di dialogo "Aggiungi transazione"](assignment.md) -Ecco un esempio del risultato dopo aver completato l'assegnazione: +[Implementare la finestra di dialogo "Aggiungi transazione"](assignment.md) + +Ecco un esempio del risultato dopo aver completato il compito: ![Screenshot che mostra un esempio di finestra di dialogo "Aggiungi transazione"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.it.png) --- -**Disclaimer**: -Questo documento è stato tradotto utilizzando il servizio di traduzione automatica [Co-op Translator](https://github.com/Azure/co-op-translator). Sebbene ci impegniamo per garantire l'accuratezza, si prega di notare che le traduzioni automatiche potrebbero contenere errori o imprecisioni. Il documento originale nella sua lingua nativa dovrebbe essere considerato la fonte autorevole. Per informazioni critiche, si consiglia una traduzione professionale eseguita da un traduttore umano. Non siamo responsabili per eventuali fraintendimenti o interpretazioni errate derivanti dall'uso di questa traduzione. \ No newline at end of file +**Disclaimer (Avvertenza)**: +Questo documento è stato tradotto utilizzando il servizio di traduzione automatica [Co-op Translator](https://github.com/Azure/co-op-translator). Sebbene ci impegniamo per garantire l'accuratezza, si prega di notare che le traduzioni automatiche possono contenere errori o imprecisioni. Il documento originale nella sua lingua nativa dovrebbe essere considerato la fonte autorevole. Per informazioni critiche, si raccomanda una traduzione professionale umana. Non siamo responsabili per eventuali incomprensioni o interpretazioni errate derivanti dall'uso di questa traduzione. \ No newline at end of file diff --git a/translations/ja/7-bank-project/4-state-management/README.md b/translations/ja/7-bank-project/4-state-management/README.md index 4ef066297..e8169e210 100644 --- a/translations/ja/7-bank-project/4-state-management/README.md +++ b/translations/ja/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# 銀行アプリを作る Part 4: 状態管理の概念 +# 銀行アプリを作ろう パート4: 状態管理の概念 ## 講義前クイズ @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### はじめに -ウェブアプリケーションが成長するにつれて、データフローを追跡するのが難しくなります。どのコードがデータを取得し、どのページがそれを使用し、どこでいつ更新が必要なのか...コードが散らかり、保守が困難になることがあります。特に、アプリの異なるページ間でデータを共有する必要がある場合、例えばユーザーデータなどでは、この問題が顕著です。*状態管理*の概念は、あらゆる種類のプログラムで常に存在していましたが、ウェブアプリがますます複雑化するにつれて、開発中に考慮すべき重要なポイントとなっています。 +ウェブアプリケーションが成長するにつれて、すべてのデータフローを追跡するのが難しくなります。どのコードがデータを取得し、どのページがそれを消費し、どこでいつ更新する必要があるのか...コードが散らかり、保守が難しくなるのは簡単です。特に、アプリの異なるページ間でデータを共有する必要がある場合、例えばユーザーデータなどではなおさらです。*状態管理*の概念はあらゆる種類のプログラムに存在していましたが、ウェブアプリがますます複雑化する中で、開発中に考慮すべき重要なポイントとなっています。 -この最終パートでは、これまでに作成したアプリを見直し、状態管理を再考し、ブラウザのリフレッシュをサポートし、ユーザーセッション間でデータを保持できるようにします。 +この最終パートでは、これまでに構築したアプリを見直し、状態管理を再考し、ブラウザのリフレッシュをサポートし、ユーザーセッション間でデータを永続化する方法を学びます。 ### 前提条件 -このレッスンでは、ウェブアプリの[データ取得](../3-data/README.md)パートを完了している必要があります。また、[Node.js](https://nodejs.org)をインストールし、[サーバーAPI](../api/README.md)をローカルで実行してアカウントデータを管理できるようにする必要があります。 +このレッスンのために、[データ取得](../3-data/README.md)パートを完了している必要があります。また、[Node.js](https://nodejs.org)をインストールし、[サーバーAPI](../api/README.md)をローカルで実行して、アカウントデータを管理できるようにする必要があります。 サーバーが正しく動作しているかどうかは、ターミナルで次のコマンドを実行して確認できます。 @@ -34,30 +34,30 @@ curl http://localhost:5000/api ## 状態管理を再考する -[前回のレッスン](../3-data/README.md)では、現在ログインしているユーザーの銀行データを含むグローバル変数`account`を使用して、アプリの基本的な状態の概念を紹介しました。しかし、現在の実装にはいくつかの欠点があります。ダッシュボードでページをリフレッシュしてみてください。何が起こりますか? +[前回のレッスン](../3-data/README.md)では、現在ログインしているユーザーの銀行データを含むグローバル変数`account`を使用して、アプリ内での基本的な状態の概念を紹介しました。しかし、現在の実装にはいくつかの欠点があります。ダッシュボードにいるときにページをリフレッシュしてみてください。何が起こりますか? 現在のコードには3つの問題があります: -- 状態が保持されていないため、ブラウザをリフレッシュするとログインページに戻ってしまいます。 -- 状態を変更する関数が複数あり、アプリが成長するにつれて変更を追跡するのが難しくなり、更新を忘れることが容易になります。 -- 状態がクリーンアップされないため、*ログアウト*をクリックしてもログインページにいる間にアカウントデータが残っています。 +- 状態が永続化されていないため、ブラウザをリフレッシュするとログインページに戻ってしまいます。 +- 状態を変更する関数が複数あり、アプリが成長するにつれて変更を追跡するのが難しくなり、更新を忘れることが簡単になります。 +- 状態がクリーンアップされないため、*ログアウト*をクリックしても、ログインページにいるのにアカウントデータが残っています。 -これらの問題を一つずつ解決するためにコードを更新することもできますが、それではコードの重複が増え、アプリがより複雑で保守が難しくなります。そこで、数分間立ち止まって戦略を再考することができます。 +これらの問題を一つずつ解決するようにコードを更新することもできますが、それではコードの重複が増え、アプリがより複雑で保守が難しくなります。そこで、数分間立ち止まって戦略を再考することができます。 > ここで本当に解決しようとしている問題は何でしょうか? -[状態管理](https://en.wikipedia.org/wiki/State_management)は、次の2つの特定の問題を解決するための良いアプローチを見つけることに関するものです: +[状態管理](https://en.wikipedia.org/wiki/State_management)とは、次の2つの特定の問題を解決するための良いアプローチを見つけることです: - アプリ内のデータフローを理解しやすくするにはどうすればよいか? - 状態データを常にユーザーインターフェースと同期させるにはどうすればよいか(その逆も同様)? -これらを解決すれば、他の問題もすでに解決されているか、解決が容易になる可能性があります。これらの問題を解決するためのアプローチは多数ありますが、ここでは**データとその変更方法を中央集約化する**という一般的な解決策を採用します。データフローは次のようになります: +これらを解決すれば、他の問題もすでに解決されているか、解決が容易になっている可能性があります。これらの問題を解決するためのアプローチは数多くありますが、ここでは**データとその変更方法を中央集約化する**という一般的な解決策を採用します。データフローは次のようになります: ![HTML、ユーザーアクション、状態間のデータフローを示すスキーマ](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.ja.png) -> データが自動的にビュー更新をトリガーする部分については、[リアクティブプログラミング](https://en.wikipedia.org/wiki/Reactive_programming)のより高度な概念に関連しているため、ここでは取り上げません。深く掘り下げたい場合には良いフォローアップのテーマです。 +> データが自動的にビューを更新する部分については、[リアクティブプログラミング](https://en.wikipedia.org/wiki/Reactive_programming)のより高度な概念に関連しているため、ここでは取り上げません。興味があれば、深掘りする良いテーマです。 -✅ 状態管理にはさまざまなアプローチを持つ多くのライブラリがありますが、[Redux](https://redux.js.org)はその中でも人気のある選択肢です。大規模なウェブアプリで直面する可能性のある問題とその解決方法を学ぶために、使用される概念やパターンを確認してみてください。 +✅ 状態管理にはさまざまなアプローチを持つ多くのライブラリがありますが、[Redux](https://redux.js.org)はその中でも人気のある選択肢です。大規模なウェブアプリで直面する可能性のある問題やその解決方法を学ぶために、使用される概念やパターンを調べてみてください。 ### タスク @@ -67,7 +67,7 @@ curl http://localhost:5000/api let account = null; ``` -次のように: +以下のように: ```js let state = { @@ -75,9 +75,9 @@ let state = { }; ``` -このアイデアは、アプリのすべてのデータを単一の状態オブジェクトに*中央集約化*することです。現在の状態には`account`しかないため、あまり変わりませんが、進化の道筋を作ります。 +このアイデアは、アプリのすべてのデータを単一の状態オブジェクトに*中央集約化*することです。現在は`account`しかないので大きな変化はありませんが、将来的な拡張の道を開きます。 -また、それを使用する関数を更新する必要があります。`register()`および`login()`関数では、`account = ...`を`state.account = ...`に置き換えます。 +また、それを使用している関数も更新する必要があります。`register()`および`login()`関数では、`account = ...`を`state.account = ...`に置き換えます。 `updateDashboard()`関数の冒頭に次の行を追加します: @@ -85,13 +85,13 @@ let state = { const account = state.account; ``` -このリファクタリング自体は大きな改善をもたらしませんでしたが、次の変更の基盤を整えることが目的でした。 +このリファクタリング自体は大きな改善をもたらしませんが、次の変更の基盤を築くことが目的です。 ## データ変更を追跡する -`state`オブジェクトをデータの保存に使用するようにしたので、次のステップは更新を中央集約化することです。これにより、変更内容とその発生時期を追跡しやすくすることが目的です。 +`state`オブジェクトをデータの保存に使用するようにしたので、次のステップは更新を中央集約化することです。これにより、変更内容や変更が発生したタイミングを追跡しやすくなります。 -`state`オブジェクトに変更を加えないようにするために、それを[*不変*](https://en.wikipedia.org/wiki/Immutable_object)と見なすことも良いプラクティスです。つまり、まったく変更できないということです。また、状態オブジェクトを変更したい場合は、新しい状態オブジェクトを作成する必要があります。これにより、望ましくない[*副作用*](https://en.wikipedia.org/wiki/Side_effect_(computer_science))を防ぐ保護が構築され、アプリに新しい機能(例えば、元に戻す/やり直しの実装)を追加する可能性が開かれます。また、デバッグが容易になります。例えば、状態に加えられたすべての変更をログに記録し、変更履歴を保持してバグの原因を理解することができます。 +`state`オブジェクトに変更を加えないようにするために、それを[*不変*](https://en.wikipedia.org/wiki/Immutable_object)と見なすのも良いプラクティスです。つまり、まったく変更できないということです。何かを変更したい場合は、新しい状態オブジェクトを作成する必要があります。これにより、望ましくない[*副作用*](https://en.wikipedia.org/wiki/Side_effect_(computer_science))を防ぐ保護が構築され、アプリに新しい機能(例えば、元に戻す/やり直しの実装)を追加する可能性が開かれます。また、デバッグが容易になります。例えば、状態に加えられたすべての変更をログに記録し、変更履歴を保持してバグの原因を理解することができます。 JavaScriptでは、[`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)を使用してオブジェクトの不変バージョンを作成できます。不変オブジェクトに変更を加えようとすると、例外が発生します。 @@ -99,7 +99,7 @@ JavaScriptでは、[`Object.freeze()`](https://developer.mozilla.org/docs/Web/Ja ### タスク -新しい`updateState()`関数を作成します: +新しい`updateState()`関数を作成しましょう: ```js function updateState(property, newData) { @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -この関数では、新しい状態オブジェクトを作成し、[*スプレッド演算子 (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals)を使用して前の状態からデータをコピーします。その後、[ブラケット記法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]`を使用して状態オブジェクトの特定のプロパティを新しいデータで上書きします。最後に、`Object.freeze()`を使用してオブジェクトをロックし、変更を防ぎます。現在の状態には`account`プロパティしか保存されていませんが、このアプローチを使用すれば、状態に必要なプロパティをいくらでも追加できます。 +この関数では、新しい状態オブジェクトを作成し、[*スプレッド演算子*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals)を使用して前の状態からデータをコピーします。その後、[ブラケット記法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties)を使用して状態オブジェクトの特定のプロパティを新しいデータで上書きします。最後に、`Object.freeze()`を使用してオブジェクトをロックし、変更を防ぎます。現在は状態に`account`プロパティしか保存されていませんが、このアプローチを使用すれば、必要に応じて状態にいくつでもプロパティを追加できます。 -初期状態も不変であることを確認するために、`state`の初期化を更新します: +また、初期状態が凍結されていることを確認するために、`state`の初期化も更新します: ```js let state = Object.freeze({ @@ -120,21 +120,21 @@ let state = Object.freeze({ }); ``` -その後、`register`関数を更新し、`state.account = result;`の代わりに次のコードを使用します: +その後、`register`関数で`state.account = result;`の代わりに次のコードを使用します: ```js updateState('account', result); ``` -同様に、`login`関数を更新し、`state.account = data;`の代わりに次のコードを使用します: +同様に、`login`関数では`state.account = data;`を次のコードに置き換えます: ```js updateState('account', data); ``` -次に、ユーザーが*ログアウト*をクリックしたときにアカウントデータがクリアされないという問題を修正します。 +次に、ユーザーが*ログアウト*をクリックしたときにアカウントデータがクリアされない問題を修正します。 -新しい`logout()`関数を作成します: +新しい関数`logout()`を作成します: ```js function logout() { @@ -147,25 +147,25 @@ function logout() { 新しいアカウントを登録し、ログアウトして再度ログインして、すべてが正しく動作することを確認してください。 -> ヒント:ブラウザの開発ツールでコンソールを開き、`updateState()`の最後に`console.log(state)`を追加して、すべての状態変更を確認できます。 +> ヒント:`updateState()`の最後に`console.log(state)`を追加し、ブラウザの開発ツールでコンソールを開くことで、すべての状態変更を確認できます。 -## 状態を保持する +## 状態を永続化する -ほとんどのウェブアプリは、正しく動作するためにデータを保持する必要があります。すべての重要なデータは通常データベースに保存され、サーバーAPIを介してアクセスされます。例えば、私たちの場合はユーザーアカウントデータです。しかし、ブラウザで実行されているクライアントアプリにデータを保持することも、ユーザーエクスペリエンスを向上させたり、読み込みパフォーマンスを改善したりするために興味深い場合があります。 +ほとんどのウェブアプリは、正しく動作するためにデータを永続化する必要があります。すべての重要なデータは通常、データベースに保存され、サーバーAPIを介してアクセスされます。例えば、今回のケースではユーザーアカウントデータです。しかし、ブラウザで実行されているクライアントアプリにデータを永続化することも、ユーザーエクスペリエンスを向上させたり、読み込みパフォーマンスを改善したりするために興味深い場合があります。 -ブラウザにデータを保持したい場合、いくつかの重要な質問を自問する必要があります: +ブラウザにデータを永続化したい場合、次のような重要な質問を自問する必要があります: -- *データは機密性が高いか?* ユーザーパスワードなどの機密データをクライアントに保存することは避けるべきです。 +- *データは機密性が高いか?* ユーザーパスワードなどの機密データをクライアントに保存するのは避けるべきです。 - *このデータをどのくらいの期間保持する必要があるか?* このデータを現在のセッションでのみアクセスする予定ですか、それとも永続的に保存したいですか? -ウェブアプリ内で情報を保存する方法は、目的に応じてさまざまです。例えば、検索クエリをURLに保存し、ユーザー間で共有可能にすることができます。また、[HTTPクッキー](https://developer.mozilla.org/docs/Web/HTTP/Cookies)を使用して、サーバーと共有する必要があるデータ(例えば[認証](https://en.wikipedia.org/wiki/Authentication)情報)を保存することもできます。 +ウェブアプリ内で情報を保存する方法は、達成したいことに応じてさまざまです。例えば、検索クエリをURLに保存し、他のユーザーと共有可能にすることができます。また、[HTTPクッキー](https://developer.mozilla.org/docs/Web/HTTP/Cookies)を使用して、サーバーと共有する必要があるデータ(例えば[認証](https://en.wikipedia.org/wiki/Authentication)情報)を保存することもできます。 -もう一つの選択肢は、データを保存するためのブラウザAPIのいずれかを使用することです。特に興味深いものが2つあります: +もう一つの選択肢は、データを保存するためのブラウザAPIの一つを使用することです。特に興味深いものが2つあります: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):現在のウェブサイトに特化したデータをセッション間で永続的に保存できる[キー/値ストア](https://en.wikipedia.org/wiki/Key%E2%80%93value_database)。保存されたデータは期限切れになりません。 -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):`localStorage`と同じように動作しますが、保存されたデータはセッション終了時(ブラウザが閉じられたとき)にクリアされます。 +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):現在のウェブサイトに特化したデータを異なるセッション間で永続化するための[キー/バリューストア](https://en.wikipedia.org/wiki/Key%E2%80%93value_database)。保存されたデータは期限切れになりません。 +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):`localStorage`と同じように動作しますが、保存されたデータはセッションが終了すると(ブラウザが閉じられると)クリアされます。 -これらのAPIはどちらも[文字列](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)形式にシリアル化する必要があります。 +これらのAPIはどちらも[文字列](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)を使用してクライアントにデータベースを作成することも可能です。これは高度なユースケースや大量のデータを保存する必要がある場合に予約されていますが、使用するのはより複雑です。 @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -これにより、ユーザーアカウントデータが保持され、以前に中央集約化したすべての状態更新のおかげで常に最新の状態になります。この時点で、これまでのリファクタリングの恩恵を受け始めています 🙂。 +これにより、ユーザーアカウントデータが永続化され、以前に中央集約化したすべての状態更新のおかげで常に最新の状態になります。この時点で、これまでのリファクタリングの恩恵を受け始めます🙂。 -データが保存されるので、アプリが読み込まれたときにそれを復元することも重要です。初期化コードが増え始めるので、`app.js`の下部にある以前のコードも含めて新しい`init`関数を作成するのが良いアイデアかもしれません: +データが保存されるので、アプリが読み込まれたときにそれを復元することも重要です。初期化コードが増え始めるので、`app.js`の最後にある以前のコードも含めて、新しい`init`関数を作成するのが良いアイデアかもしれません: ```js function init() { @@ -202,11 +202,11 @@ function init() { init(); ``` -ここでは保存されたデータを取得し、データがあれば状態を適切に更新します。ページ更新中に状態に依存するコードがある可能性があるため、ルートを更新する*前に*これを行うことが重要です。 +ここでは保存されたデータを取得し、データがあれば状態をそれに応じて更新します。ページ更新中に状態に依存するコードがある可能性があるため、これは*ルートを更新する前に*行うことが重要です。 -また、アカウントデータを保持するようになったので、*ダッシュボード*ページをアプリケーションのデフォルトページにすることもできます。データが見つからない場合、ダッシュボードはログインページへのリダイレクトを処理します。`updateRoute()`では、フォールバック`return navigate('/login');`を`return navigate('/dashboard');`に置き換えます。 +また、アカウントデータを永続化するようになったので、*ダッシュボード*ページをアプリケーションのデフォルトページにすることもできます。データが見つからない場合、ダッシュボードは*ログイン*ページにリダイレクトする処理を行います。`updateRoute()`で、フォールバックの`return navigate('/login');`を`return navigate('/dashboard');`に置き換えます。 -アプリにログインしてページをリフレッシュしてみてください。ダッシュボードに留まるはずです。この更新により、すべての初期問題を解決しました... +アプリにログインしてページをリフレッシュしてみてください。ダッシュボードに留まるはずです。この更新で、最初の問題をすべて解決しました... ## データをリフレッシュする @@ -221,15 +221,15 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -ブラウザでダッシュボードページをリフレッシュしてみてください。何が起こりますか?新しいトランザクションが表示されますか? +その後、ブラウザでダッシュボードページをリフレッシュしてみてください。何が起こりますか?新しいトランザクションが表示されますか? -状態は`localStorage`のおかげで無期限に保持されますが、それはログアウトして再度ログインするまで更新されないことも意味します! +状態は`localStorage`のおかげで無期限に永続化されますが、それはログアウトして再度ログインするまで更新されないことも意味します! -これを修正するための一つの戦略は、ダッシュボードが読み込まれるたびにアカウントデータを再読み込みし、古いデータを避けることです。 +これを修正するための一つの戦略は、ダッシュボードが読み込まれるたびにアカウントデータをリロードし、古いデータを回避することです。 ### タスク -新しい`updateAccountData`関数を作成します: +新しい関数`updateAccountData`を作成します: ```js async function updateAccountData() { @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -このメソッドは、現在ログインしていることを確認し、サーバーからアカウントデータを再読み込みします。 +このメソッドは、現在ログインしていることを確認し、サーバーからアカウントデータをリロードします。 次に、`refresh`という名前の別の関数を作成します: @@ -273,22 +273,22 @@ const routes = { ## 🚀 チャレンジ -ダッシュボードが読み込まれるたびにアカウントデータを再読み込みするようになった今、*すべてのアカウント*データを保持する必要があると思いますか? +ダッシュボードが読み込まれるたびにアカウントデータをリロードするようになった今、*すべてのアカウント*データを永続化する必要があると思いますか? -チームで協力して、`localStorage`に保存および読み込む内容をアプリが動作するために絶対に必要なものだけに変更してみてください。 +アプリの動作に絶対に必要なものだけを`localStorage`に保存および読み込むように変更してみてください。 ## 講義後クイズ - -[講義後クイズ](https://ff-quizzes.netlify.app/web/quiz/48) +[講義後のクイズ](https://ff-quizzes.netlify.app/web/quiz/48) ## 課題 -[「取引を追加」ダイアログの実装](assignment.md) -以下は、課題を完了した後の例としての結果です: +[「取引を追加」ダイアログを実装する](assignment.md) + +課題を完了した後の例はこちらです: ![「取引を追加」ダイアログの例を示すスクリーンショット](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.ja.png) --- **免責事項**: -この文書は、AI翻訳サービス [Co-op Translator](https://github.com/Azure/co-op-translator) を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。 \ No newline at end of file +この文書は、AI翻訳サービス[Co-op Translator](https://github.com/Azure/co-op-translator)を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当方は責任を負いません。 \ No newline at end of file diff --git a/translations/ko/7-bank-project/4-state-management/README.md b/translations/ko/7-bank-project/4-state-management/README.md index c1deceebb..f222744dd 100644 --- a/translations/ko/7-bank-project/4-state-management/README.md +++ b/translations/ko/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ # Sukurkite bankinę programėlę, 4 dalis: Būsenos valdymo koncepcijos -## Klausimai prieš paskaitą +## Klausimynas prieš paskaitą -[Prieš paskaitą pateikiamas klausimynas](https://ff-quizzes.netlify.app/web/quiz/47) +[Klausimynas prieš paskaitą](https://ff-quizzes.netlify.app/web/quiz/47) ### Įvadas -Kai internetinė programėlė auga, tampa sudėtinga sekti visus duomenų srautus. Kuris kodas gauna duomenis, kuris puslapis juos naudoja, kur ir kada juos reikia atnaujinti... lengva pasimesti ir sukurti netvarkingą kodą, kurį sunku prižiūrėti. Tai ypač aktualu, kai reikia dalintis duomenimis tarp skirtingų programėlės puslapių, pavyzdžiui, vartotojo duomenimis. *Būsenos valdymo* koncepcija visada egzistavo įvairiose programose, tačiau, augant internetinių programėlių sudėtingumui, tai tapo svarbiu aspektu kuriant programas. +Kai internetinė programėlė auga, tampa sudėtinga sekti visus duomenų srautus. Kuris kodas gauna duomenis, kuris puslapis juos naudoja, kur ir kada jie turi būti atnaujinami... lengva pasimesti tarp netvarkingo kodo, kurį sunku prižiūrėti. Tai ypač aktualu, kai reikia dalintis duomenimis tarp skirtingų programėlės puslapių, pavyzdžiui, vartotojo duomenimis. *Būsenos valdymo* koncepcija visada egzistavo įvairiose programose, tačiau internetinėms programėlėms tampant vis sudėtingesnėms, tai tapo svarbiu aspektu, apie kurį reikia galvoti kuriant. -Šioje paskutinėje dalyje peržiūrėsime sukurtą programėlę, kad iš naujo apgalvotume, kaip valdoma būsena, leisdami palaikyti naršyklės atnaujinimą bet kuriuo metu ir išsaugoti duomenis tarp vartotojo sesijų. +Šioje paskutinėje dalyje peržiūrėsime sukurtą programėlę, kad iš naujo apgalvotume, kaip valdoma būsena, suteikiant galimybę naršyklėje atnaujinti puslapį bet kuriuo metu ir išsaugoti duomenis tarp vartotojo sesijų. ### Privalomos sąlygos -Prieš šią pamoką turite būti baigę [duomenų gavimo](../3-data/README.md) dalį. Taip pat turite įdiegti [Node.js](https://nodejs.org) ir [paleisti serverio API](../api/README.md) lokaliai, kad galėtumėte valdyti paskyros duomenis. +Turite būti baigę [duomenų gavimo](../3-data/README.md) dalį šiai pamokai. Taip pat turite įdiegti [Node.js](https://nodejs.org) ir [paleisti serverio API](../api/README.md) lokaliai, kad galėtumėte valdyti paskyros duomenis. Galite patikrinti, ar serveris veikia tinkamai, vykdydami šią komandą terminale: @@ -34,9 +34,9 @@ curl http://localhost:5000/api ## Iš naujo apgalvokite būsenos valdymą -[Ankstesnėje pamokoje](../3-data/README.md) pristatėme pagrindinę būsenos koncepciją mūsų programėlėje su globaliu `account` kintamuoju, kuris saugo prisijungusio vartotojo banko duomenis. Tačiau dabartinėje implementacijoje yra keletas trūkumų. Pabandykite atnaujinti puslapį, kai esate prietaisų skydelyje. Kas nutinka? +[Ankstesnėje pamokoje](../3-data/README.md) pristatėme pagrindinę būsenos koncepciją mūsų programėlėje su globaliu `account` kintamuoju, kuriame saugomi šiuo metu prisijungusio vartotojo banko duomenys. Tačiau dabartinis įgyvendinimas turi tam tikrų trūkumų. Pabandykite atnaujinti puslapį, kai esate prietaisų skydelyje. Kas nutinka? -Šiuo metu yra trys problemos: +Dabartiniame kode yra 3 problemos: - Būsena nėra išsaugoma, nes naršyklės atnaujinimas grąžina jus į prisijungimo puslapį. - Yra kelios funkcijos, kurios keičia būseną. Kai programėlė auga, tampa sunku sekti pakeitimus, ir lengva pamiršti atnaujinti vieną iš jų. @@ -51,13 +51,13 @@ Galėtume atnaujinti savo kodą, kad išspręstume šias problemas po vieną, ta - Kaip padaryti, kad duomenų srautai programėlėje būtų suprantami? - Kaip užtikrinti, kad būsenos duomenys visada būtų sinchronizuoti su vartotojo sąsaja (ir atvirkščiai)? -Kai pasirūpinsite šiomis problemomis, bet kokios kitos problemos, su kuriomis galite susidurti, gali būti jau išspręstos arba tapti lengviau išsprendžiamos. Yra daug galimų būdų šioms problemoms spręsti, tačiau mes pasirinkime bendrą sprendimą, kuris apima **duomenų ir jų keitimo būdų centralizavimą**. Duomenų srautai atrodytų taip: +Kai pasirūpinsite šiomis problemomis, bet kokios kitos problemos, su kuriomis galite susidurti, gali būti jau išspręstos arba tapti lengviau išsprendžiamos. Yra daug galimų būdų šioms problemoms spręsti, tačiau mes pasirinkime bendrą sprendimą, kuris susideda iš **duomenų ir jų keitimo būdų centralizavimo**. Duomenų srautai atrodytų taip: ![Schema, rodanti duomenų srautus tarp HTML, vartotojo veiksmų ir būsenos](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.lt.png) -> Čia neaptarsime dalies, kurioje duomenys automatiškai atnaujina vaizdą, nes tai susiję su pažangesnėmis [reaktyviosios programavimo](https://en.wikipedia.org/wiki/Reactive_programming) koncepcijomis. Tai gera tema gilintis, jei norite išsamiau suprasti. +> Čia neaptarsime dalies, kurioje duomenys automatiškai atnaujina vaizdą, nes tai susiję su pažangesnėmis [reaktyviosios programavimo](https://en.wikipedia.org/wiki/Reactive_programming) koncepcijomis. Tai gera tema gilintis, jei norite daugiau sužinoti. -✅ Yra daug bibliotekų su skirtingais būsenos valdymo metodais, [Redux](https://redux.js.org) yra populiarus pasirinkimas. Susipažinkite su naudojamomis koncepcijomis ir šablonais, nes tai dažnai yra geras būdas sužinoti, su kokiomis problemomis galite susidurti didelėse internetinėse programėlėse ir kaip jas galima išspręsti. +✅ Yra daug bibliotekų su skirtingais būsenos valdymo metodais, [Redux](https://redux.js.org) yra populiarus pasirinkimas. Susipažinkite su naudojamomis koncepcijomis ir šablonais, nes tai dažnai yra geras būdas sužinoti, su kokiomis potencialiomis problemomis galite susidurti didelėse internetinėse programėlėse ir kaip jas galima išspręsti. ### Užduotis @@ -75,7 +75,7 @@ let state = { }; ``` -Idėja yra *centralizuoti* visus mūsų programėlės duomenis viename būsenos objekte. Šiuo metu būsenoje turime tik `account`, todėl tai daug nepakeičia, tačiau tai sukuria pagrindą ateities pakeitimams. +Idėja yra *centralizuoti* visus mūsų programėlės duomenis viename būsenos objekte. Šiuo metu būsenoje turime tik `account`, todėl tai daug nepakeičia, tačiau tai sukuria pagrindą ateities pokyčiams. Taip pat turime atnaujinti funkcijas, kurios jį naudoja. `register()` ir `login()` funkcijose pakeiskite `account = ...` į `state.account = ...`; @@ -85,17 +85,17 @@ Taip pat turime atnaujinti funkcijas, kurios jį naudoja. `register()` ir `login const account = state.account; ``` -Šis pertvarkymas pats savaime neatnešė daug patobulinimų, tačiau idėja buvo sukurti pagrindą kitiems pakeitimams. +Šis pertvarkymas pats savaime neatnešė daug patobulinimų, tačiau idėja buvo sukurti pagrindą tolesniems pakeitimams. -## Sekite duomenų pakeitimus +## Sekite duomenų pokyčius -Dabar, kai sukūrėme `state` objektą duomenims saugoti, kitas žingsnis yra centralizuoti atnaujinimus. Tikslas yra palengvinti bet kokių pakeitimų sekimą ir supratimą, kada jie įvyksta. +Dabar, kai sukūrėme `state` objektą duomenims saugoti, kitas žingsnis yra centralizuoti atnaujinimus. Tikslas yra palengvinti bet kokių pokyčių sekimą ir supratimą, kada jie įvyksta. -Kad būtų išvengta pakeitimų `state` objekte, taip pat yra gera praktika laikyti jį [*nekintamu*](https://en.wikipedia.org/wiki/Immutable_object), tai reiškia, kad jo negalima visiškai modifikuoti. Tai taip pat reiškia, kad jei norite ką nors pakeisti, turite sukurti naują būsenos objektą. Taip apsisaugosite nuo galimų nepageidaujamų [šalutinių poveikių](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) ir atversite galimybes naujoms funkcijoms, tokioms kaip atšaukimo/atstatymo įgyvendinimas, taip pat palengvinsite derinimą. Pavyzdžiui, galėtumėte registruoti kiekvieną būsenos pakeitimą ir išsaugoti jų istoriją, kad suprastumėte klaidos šaltinį. +Kad būtų išvengta pokyčių `state` objekte, taip pat yra gera praktika laikyti jį [*nepakeičiamu*](https://en.wikipedia.org/wiki/Immutable_object), tai reiškia, kad jo negalima visiškai modifikuoti. Tai taip pat reiškia, kad jei norite ką nors pakeisti, turite sukurti naują būsenos objektą. Tokiu būdu apsisaugosite nuo galimų nepageidaujamų [šalutinių poveikių](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) ir atversite galimybes naujoms funkcijoms, tokioms kaip atšaukimo/atstatymo įgyvendinimas, taip pat palengvinsite derinimą. Pavyzdžiui, galėtumėte registruoti kiekvieną būsenos pakeitimą ir išlaikyti jų istoriją, kad suprastumėte klaidos šaltinį. -JavaScript'e galite naudoti [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), kad sukurtumėte nekintamą objekto versiją. Jei bandysite pakeisti nekintamą objektą, bus išmesta išimtis. +JavaScript'e galite naudoti [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), kad sukurtumėte nepakeičiamą objekto versiją. Jei bandysite pakeisti nepakeičiamą objektą, bus išmesta išimtis. -✅ Ar žinote skirtumą tarp *paviršutiniškai* ir *giliai* nekintamo objekto? Apie tai galite paskaityti [čia](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Ar žinote skirtumą tarp *paviršutiniškai* ir *giliai* nepakeičiamo objekto? Galite apie tai paskaityti [čia](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Užduotis @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Šioje funkcijoje sukuriame naują būsenos objektą ir kopijuojame duomenis iš ankstesnės būsenos naudodami [*sklaidos operatorių (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Tada perrašome tam tikrą būsenos objekto savybę naujais duomenimis naudodami [skliaustelių notaciją](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]`. Galiausiai užrakiname objektą, kad išvengtume pakeitimų, naudodami `Object.freeze()`. Šiuo metu būsenoje saugome tik `account`, tačiau naudodami šį metodą galime pridėti tiek savybių, kiek reikia. +Šioje funkcijoje sukuriame naują būsenos objektą ir kopijuojame duomenis iš ankstesnės būsenos naudodami [*sklaidos operatorių (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Tada perrašome tam tikrą būsenos objekto savybę naujais duomenimis naudodami [skliaustelių notaciją](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` priskyrimui. Galiausiai užrakiname objektą, kad išvengtume modifikacijų, naudodami `Object.freeze()`. Šiuo metu būsenoje saugome tik `account` savybę, tačiau naudodami šį metodą galite pridėti tiek savybių, kiek reikia. Taip pat atnaujinsime `state` inicializaciją, kad įsitikintume, jog pradinė būsena taip pat yra užšaldyta: @@ -120,7 +120,7 @@ let state = Object.freeze({ }); ``` -Po to atnaujinkite `register` funkciją, pakeisdami `state.account = result;` į: +Po to atnaujinkite `register` funkciją, pakeisdami `state.account = result;` priskyrimą į: ```js updateState('account', result); @@ -143,35 +143,35 @@ function logout() { } ``` -`updateDashboard()` funkcijoje pakeiskite peradresavimą `return navigate('/login');` į `return logout();` +`updateDashboard()` funkcijoje pakeiskite peradresavimą `return navigate('/login');` į `return logout()`; -Pabandykite užregistruoti naują paskyrą, atsijungti ir vėl prisijungti, kad patikrintumėte, ar viskas veikia tinkamai. +Pabandykite užregistruoti naują paskyrą, atsijungti ir vėl prisijungti, kad patikrintumėte, ar viskas vis dar veikia tinkamai. -> Patarimas: galite peržiūrėti visus būsenos pakeitimus, pridėdami `console.log(state)` `updateState()` funkcijos apačioje ir atidarę naršyklės kūrimo įrankių konsolę. +> Patarimas: galite peržiūrėti visus būsenos pokyčius, pridėdami `console.log(state)` `updateState()` apačioje ir atidarę naršyklės kūrimo įrankių konsolę. ## Išsaugokite būseną -Dauguma internetinių programėlių turi išsaugoti duomenis, kad galėtų tinkamai veikti. Visi svarbūs duomenys paprastai saugomi duomenų bazėje ir pasiekiami per serverio API, kaip mūsų atveju vartotojo paskyros duomenys. Tačiau kartais taip pat naudinga išsaugoti kai kuriuos duomenis kliento programėlėje, kuri veikia jūsų naršyklėje, siekiant geresnės vartotojo patirties arba pagerinti įkėlimo našumą. +Daugumai internetinių programėlių reikia išsaugoti duomenis, kad jos galėtų tinkamai veikti. Visi svarbūs duomenys paprastai saugomi duomenų bazėje ir pasiekiami per serverio API, kaip mūsų atveju vartotojo paskyros duomenys. Tačiau kartais taip pat naudinga išsaugoti kai kuriuos duomenis kliento programėlėje, kuri veikia jūsų naršyklėje, siekiant geresnės vartotojo patirties arba pagerinti įkėlimo našumą. Kai norite išsaugoti duomenis naršyklėje, turėtumėte užduoti sau keletą svarbių klausimų: - *Ar duomenys yra jautrūs?* Turėtumėte vengti saugoti bet kokius jautrius duomenis kliente, pavyzdžiui, vartotojo slaptažodžius. -- *Kiek laiko jums reikia išlaikyti šiuos duomenis?* Ar planuojate naudoti šiuos duomenis tik dabartinei sesijai, ar norite, kad jie būtų saugomi visam laikui? +- *Kiek laiko jums reikia išlaikyti šiuos duomenis?* Ar planuojate pasiekti šiuos duomenis tik dabartinei sesijai, ar norite, kad jie būtų saugomi visam laikui? -Yra keli būdai saugoti informaciją internetinėje programėlėje, priklausomai nuo to, ką norite pasiekti. Pavyzdžiui, galite naudoti URL, kad saugotumėte paieškos užklausą ir padarytumėte ją dalinamą tarp vartotojų. Taip pat galite naudoti [HTTP slapukus](https://developer.mozilla.org/docs/Web/HTTP/Cookies), jei duomenys turi būti bendrinami su serveriu, pavyzdžiui, [autentifikacijos](https://en.wikipedia.org/wiki/Authentication) informacija. +Yra keli būdai saugoti informaciją internetinėje programėlėje, priklausomai nuo to, ką norite pasiekti. Pavyzdžiui, galite naudoti URL, kad saugotumėte paieškos užklausą ir padarytumėte ją dalinamą tarp vartotojų. Taip pat galite naudoti [HTTP slapukus](https://developer.mozilla.org/docs/Web/HTTP/Cookies), jei duomenys turi būti dalinami su serveriu, pavyzdžiui, [autentifikacijos](https://en.wikipedia.org/wiki/Authentication) informacija. Kita galimybė yra naudoti vieną iš daugelio naršyklės API duomenims saugoti. Dvi iš jų yra ypač įdomios: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Raktų/Verčių saugykla](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), leidžianti išsaugoti duomenis, susijusius su dabartine svetaine, tarp skirtingų sesijų. Išsaugoti duomenys niekada neišnyksta. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): veikia taip pat kaip `localStorage`, išskyrus tai, kad saugomi duomenys ištrinami, kai sesija baigiasi (kai naršyklė uždaroma). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Raktų/Verčių saugykla](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), leidžianti išsaugoti duomenis, specifinius dabartinei svetainei, tarp skirtingų sesijų. Joje saugomi duomenys niekada nesibaigia. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ši veikia taip pat kaip `localStorage`, išskyrus tai, kad joje saugomi duomenys ištrinami, kai sesija baigiasi (kai naršyklė uždaroma). Atkreipkite dėmesį, kad abi šios API leidžia saugoti tik [eilutes](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Jei norite saugoti sudėtingus objektus, turėsite juos serializuoti į [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) formatą, naudodami [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Jei norite sukurti internetinę programėlę, kuri neveikia su serveriu, taip pat galima sukurti duomenų bazę kliente, naudojant [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ši galimybė skirta pažangesniems atvejams arba jei reikia saugoti didelį duomenų kiekį, nes ją naudoti yra sudėtingiau. +✅ Jei norite sukurti internetinę programėlę, kuri neveikia su serveriu, taip pat galima sukurti duomenų bazę kliente, naudojant [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ši API skirta pažangesniems atvejams arba jei reikia saugoti didelį duomenų kiekį, nes ją naudoti yra sudėtingiau. ### Užduotis -Norime, kad mūsų vartotojai liktų prisijungę, kol jie aiškiai nepaspaudžia *Atsijungti* mygtuko, todėl naudosime `localStorage`, kad išsaugotume paskyros duomenis. Pirmiausia apibrėžkime raktą, kurį naudosime duomenims saugoti. +Norime, kad mūsų vartotojai liktų prisijungę, kol jie aiškiai nepaspaus *Atsijungti* mygtuko, todėl naudosime `localStorage`, kad saugotume paskyros duomenis. Pirmiausia apibrėžkime raktą, kurį naudosime duomenims saugoti. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ Tada pridėkite šią eilutę `updateState()` funkcijos pabaigoje: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Taip vartotojo paskyros duomenys bus išsaugoti ir visada atnaujinami, nes anksčiau centralizavome visus būsenos atnaujinimus. Štai kur pradedame naudotis visais ankstesniais pertvarkymais 🙂. +Su tuo vartotojo paskyros duomenys bus išsaugoti ir visada atnaujinami, nes anksčiau centralizavome visus būsenos atnaujinimus. Čia pradedame naudotis visais ankstesniais pertvarkymais 🙂. -Kadangi duomenys yra išsaugoti, taip pat turime pasirūpinti jų atkūrimu, kai programėlė įkeliama. Kadangi pradėsime turėti daugiau inicializacijos kodo, gali būti gera idėja sukurti naują `init` funkciją, kuri taip pat apimtų ankstesnį kodą `app.js` apačioje: +Kadangi duomenys yra išsaugoti, taip pat turime pasirūpinti jų atkūrimu, kai programėlė įkeliama. Kadangi pradėsime turėti daugiau inicializacijos kodo, gali būti gera idėja sukurti naują `init` funkciją, kuri taip pat apimtų mūsų ankstesnį kodą `app.js` apačioje: ```js function init() { @@ -223,9 +223,9 @@ curl --request POST \ Dabar pabandykite atnaujinti prietaisų skydelio puslapį naršyklėje. Kas nutinka? Ar matote naują operaciją? -Būsena yra išsaugota neribotam laikui dėl `localStorage`, tačiau tai taip pat reiškia, kad ji niekada neatnaujinama, kol neišsijungiate iš programėlės ir vėl neprisijungiate! +Būsena yra išsaugota neribotam laikui dėl `localStorage`, tačiau tai taip pat reiškia, kad ji niekada nėra atnaujinama, kol neišsijungiate iš programėlės ir vėl neprisijungiate! -Vienas galimas sprendimas yra atnaujinti paskyros duomenis kiekvieną kartą, kai įkeliama prietaisų skydelio puslapis, kad būtų išvengta pasenusių duomenų. +Vienas galimas strategijos būdas tai išspręsti yra atnaujinti paskyros duomenis kiekvieną kartą, kai įkeliama prietaisų skydelio puslapis, kad būtų išvengta pasenusių duomenų. ### Užduotis @@ -258,23 +258,18 @@ async function refresh() { } ``` -Ši funkcija atnaujina paskyros duomenis, tada pasirūpina prietaisų skydelio puslapio HTML atnaujinimu. Tai yra tai, ką turime iškviesti, kai įkeliama prietaisų skydelio maršrutas. Atnaujinkite maršruto apibrėžimą su: +Ši funkcija atnaujina paskyros duomenis, tada pasirūpina prietaisų skydelio puslapio HTML atnaujinimu. Tai yra tai, ką turime iškviesti, kai įkeli +[Po paskaitos testas](https://ff-quizzes.netlify.app/web/quiz/48) -```js -const routes = { - '/login': { templateId: 'login' }, - '/dashboard': { templateId: 'dashboard', init: refresh } -}; -``` +## Užduotis -Dabar pabandykite atnaujinti -[Įgyvendinti „Pridėti operaciją“ dialogą](assignment.md) +[Įgyvendinti "Pridėti operaciją" dialogą](assignment.md) -Štai pavyzdys, kaip turėtų atrodyti dialogas po užduoties atlikimo: +Štai pavyzdys, kaip turėtų atrodyti rezultatas po užduoties atlikimo: -![Ekrano nuotrauka, rodanti pavyzdinį „Pridėti operaciją“ dialogą](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.lt.png) +![Ekrano nuotrauka, rodanti pavyzdinį "Pridėti operaciją" dialogą](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.lt.png) --- -**Atsakomybės apribojimas**: -Šis dokumentas buvo išverstas naudojant AI vertimo paslaugą [Co-op Translator](https://github.com/Azure/co-op-translator). Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama profesionali žmogaus vertimo paslauga. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus interpretavimus, atsiradusius naudojant šį vertimą. \ No newline at end of file +**Atsakomybės atsisakymas**: +Šis dokumentas buvo išverstas naudojant AI vertimo paslaugą [Co-op Translator](https://github.com/Azure/co-op-translator). Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Dėl svarbios informacijos rekomenduojama profesionali žmogaus vertimo paslauga. Mes neprisiimame atsakomybės už nesusipratimus ar neteisingus aiškinimus, kylančius dėl šio vertimo naudojimo. \ No newline at end of file diff --git a/translations/mo/7-bank-project/4-state-management/README.md b/translations/mo/7-bank-project/4-state-management/README.md index ca1a97f8f..8bb1f3ad3 100644 --- a/translations/mo/7-bank-project/4-state-management/README.md +++ b/translations/mo/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ # बँकिंग अ‍ॅप तयार करा भाग 4: स्टेट मॅनेजमेंटची संकल्पना -## प्री-लेक्चर क्विझ +## पूर्व-व्याख्यान प्रश्नमंजुषा -[प्री-लेक्चर क्विझ](https://ff-quizzes.netlify.app/web/quiz/47) +[पूर्व-व्याख्यान प्रश्नमंजुषा](https://ff-quizzes.netlify.app/web/quiz/47) ### परिचय -वेब अ‍ॅप्लिकेशन मोठे होत असताना, डेटा फ्लो ट्रॅक करणे आव्हानात्मक होते. कोणता कोड डेटा मिळवतो, कोणते पृष्ठ त्याचा वापर करते, तो कधी आणि कुठे अपडेट करायचा... हे सर्व व्यवस्थित ठेवणे कठीण होऊ शकते. विशेषतः जेव्हा तुम्हाला तुमच्या अ‍ॅपच्या वेगवेगळ्या पृष्ठांमध्ये डेटा शेअर करायचा असतो, जसे की वापरकर्त्याचा डेटा. *स्टेट मॅनेजमेंट* ही संकल्पना सर्व प्रकारच्या प्रोग्राम्समध्ये नेहमीच अस्तित्वात असते, परंतु वेब अ‍ॅप्स अधिक जटिल होत असल्याने विकासादरम्यान यावर विचार करणे महत्त्वाचे ठरते. +जसे जसे वेब अ‍ॅप्लिकेशन मोठे होते, तसतसे सर्व डेटा प्रवाहांचा मागोवा ठेवणे कठीण होते. कोणता कोड डेटा मिळवतो, कोणते पृष्ठ तो वापरते, तो कधी आणि कुठे अद्यतनित करायचा आहे... हे सर्व लक्षात ठेवणे कठीण होऊ शकते आणि त्यामुळे कोड गोंधळलेला आणि देखभाल करणे कठीण होतो. हे विशेषतः खरे आहे जेव्हा तुम्हाला तुमच्या अ‍ॅपच्या वेगवेगळ्या पृष्ठांमध्ये डेटा सामायिक करायचा असतो, जसे की वापरकर्त्याचा डेटा. *स्टेट मॅनेजमेंट* ही संकल्पना सर्व प्रकारच्या प्रोग्राम्समध्ये नेहमीच अस्तित्वात होती, परंतु वेब अ‍ॅप्सची जटिलता वाढत असल्याने विकासादरम्यान याचा विचार करणे महत्त्वाचे ठरते. -या अंतिम भागात, आपण तयार केलेल्या अ‍ॅपवर पुनर्विचार करू आणि स्टेट कसे व्यवस्थापित केले जाते ते पाहू, ब्राउझर रिफ्रेशला कोणत्याही वेळी समर्थन देणे आणि वापरकर्ता सत्रांमध्ये डेटा टिकवून ठेवणे यासाठी. +या अंतिम भागात, आपण तयार केलेल्या अ‍ॅपवर पुनर्विचार करू आणि स्टेट कसे व्यवस्थापित करायचे यावर लक्ष केंद्रित करू, ज्यामुळे कोणत्याही क्षणी ब्राउझर रीफ्रेशला समर्थन मिळेल आणि वापरकर्ता सत्रांमध्ये डेटा टिकवून ठेवता येईल. -### पूर्वतयारी +### पूर्वअट -या धड्यासाठी तुम्ही वेब अ‍ॅपचा [डेटा फेचिंग](../3-data/README.md) भाग पूर्ण केला असावा. तुम्हाला [Node.js](https://nodejs.org) स्थापित करणे आणि [सर्व्हर API चालवणे](../api/README.md) स्थानिक पातळीवर आवश्यक आहे जेणेकरून तुम्ही खाते डेटा व्यवस्थापित करू शकता. +या धड्यासाठी तुम्ही [डेटा फेचिंग](../3-data/README.md) भाग पूर्ण केलेला असणे आवश्यक आहे. तुम्हाला [Node.js](https://nodejs.org) स्थापित करणे आणि [सर्व्हर API](../api/README.md) स्थानिकरित्या चालवणे आवश्यक आहे जेणेकरून तुम्ही खाते डेटा व्यवस्थापित करू शकाल. -सर्व्हर योग्यरित्या चालू आहे का हे तपासण्यासाठी तुम्ही टर्मिनलमध्ये हा आदेश चालवू शकता: +तुम्ही टर्मिनलमध्ये हा आदेश चालवून सर्व्हर योग्यरित्या चालू आहे का ते तपासू शकता: ```sh curl http://localhost:5000/api @@ -34,40 +34,40 @@ curl http://localhost:5000/api ## स्टेट मॅनेजमेंटवर पुनर्विचार करा -[मागील धडा](../3-data/README.md) मध्ये, आम्ही `account` नावाच्या ग्लोबल व्हेरिएबलसह अ‍ॅपमध्ये स्टेटची मूलभूत संकल्पना सादर केली होती, ज्यामध्ये सध्या लॉग इन केलेल्या वापरकर्त्याचा बँक डेटा आहे. परंतु, आमच्या सध्याच्या अंमलबजावणीमध्ये काही त्रुटी आहेत. डॅशबोर्डवर असताना पृष्ठ रिफ्रेश करण्याचा प्रयत्न करा. काय होते? +[मागील धड्यात](../3-data/README.md), आम्ही `account` नावाच्या ग्लोबल व्हेरिएबलसह अ‍ॅपमध्ये स्टेटची मूलभूत संकल्पना सादर केली, ज्यामध्ये सध्या लॉग इन केलेल्या वापरकर्त्याचा बँक डेटा आहे. तथापि, आमच्या सध्याच्या अंमलबजावणीत काही त्रुटी आहेत. डॅशबोर्डवर असताना पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. काय होते? सध्याच्या कोडमध्ये 3 समस्या आहेत: -- स्टेट टिकवून ठेवले जात नाही, कारण ब्राउझर रिफ्रेश तुम्हाला लॉगिन पृष्ठावर परत नेते. -- स्टेट बदलण्यासाठी अनेक फंक्शन्स आहेत. अ‍ॅप मोठा होत असताना, बदल ट्रॅक करणे कठीण होऊ शकते आणि एखादा अपडेट विसरणे सोपे होते. -- स्टेट साफ केली जात नाही, त्यामुळे तुम्ही *Logout* क्लिक केल्यावरही लॉगिन पृष्ठावर असताना खाते डेटा तिथेच राहतो. +- स्टेट टिकवून ठेवली जात नाही, कारण ब्राउझर रीफ्रेश केल्यावर तुम्हाला लॉगिन पृष्ठावर परत नेले जाते. +- स्टेट बदलण्यासाठी अनेक फंक्शन्स आहेत. अ‍ॅप मोठे होत असताना, बदलांचा मागोवा ठेवणे कठीण होऊ शकते आणि एखाद्या अद्यतनाची आठवण राहू शकते. +- स्टेट साफ केली जात नाही, त्यामुळे जेव्हा तुम्ही *लॉगआउट* क्लिक करता, तेव्हा लॉगिन पृष्ठावर असतानाही खाते डेटा तिथेच राहतो. -आम्ही या समस्यांवर एक-एक करून उपाय करण्यासाठी आमचा कोड अपडेट करू शकतो, परंतु यामुळे कोड डुप्लिकेशन वाढेल आणि अ‍ॅप अधिक जटिल आणि देखभाल करणे कठीण होईल. किंवा आम्ही काही मिनिटे थांबून आमची रणनीती पुन्हा विचार करू शकतो. +आपण या समस्यांवर एक एक करून उपाय करण्यासाठी कोड अद्यतनित करू शकतो, परंतु यामुळे कोड डुप्लिकेशन वाढेल आणि अ‍ॅप अधिक जटिल आणि देखभाल करणे कठीण होईल. किंवा आपण काही मिनिटे थांबून आपल्या रणनीतीचा पुनर्विचार करू शकतो. -> आम्ही येथे कोणत्या समस्या सोडवण्याचा प्रयत्न करत आहोत? +> येथे आपण खरोखर कोणत्या समस्यांचे निराकरण करण्याचा प्रयत्न करत आहोत? -[स्टेट मॅनेजमेंट](https://en.wikipedia.org/wiki/State_management) म्हणजे या दोन विशिष्ट समस्यांचे चांगले समाधान शोधणे: +[स्टेट मॅनेजमेंट](https://en.wikipedia.org/wiki/State_management) म्हणजे या दोन विशिष्ट समस्यांचे निराकरण करण्यासाठी चांगला दृष्टिकोन शोधणे: -- अ‍ॅपमधील डेटा फ्लो समजण्यासारखा कसा ठेवायचा? +- अ‍ॅपमधील डेटा प्रवाह समजण्यासारखा कसा ठेवायचा? - स्टेट डेटा नेहमी वापरकर्ता इंटरफेससह (आणि उलट) समक्रमित कसा ठेवायचा? -एकदा तुम्ही याची काळजी घेतली की, तुम्हाला असलेल्या इतर कोणत्याही समस्या आधीच सोडवल्या जाऊ शकतात किंवा सोडवणे सोपे झाले आहे. या समस्यांचे निराकरण करण्यासाठी अनेक संभाव्य दृष्टिकोन आहेत, परंतु आम्ही **डेटा आणि त्यात बदल करण्याचे मार्ग केंद्रीकृत करण्याचे** सामान्य समाधान निवडू. डेटा फ्लो असे असेल: +एकदा तुम्ही यांची काळजी घेतली की, तुम्हाला असलेल्या इतर कोणत्याही समस्या कदाचित आधीच निराकरण झाल्या असतील किंवा त्या सोडवणे सोपे झाले असेल. या समस्यांचे निराकरण करण्यासाठी अनेक दृष्टिकोन आहेत, परंतु आम्ही **डेटा आणि तो बदलण्याच्या पद्धती केंद्रीकृत करण्याचा** एक सामान्य उपाय निवडू. डेटा प्रवाह असा असेल: -![HTML, वापरकर्ता क्रिया आणि स्टेट यामधील डेटा फ्लो दर्शवणारी योजना](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.mr.png) +![HTML, वापरकर्ता क्रिया आणि स्टेट यांच्यातील डेटा प्रवाह दर्शविणारी योजना](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.mr.png) -> आम्ही येथे डेटा स्वयंचलितपणे दृश्य अपडेट ट्रिगर करण्याचा भाग कव्हर करणार नाही, कारण ते [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) च्या अधिक प्रगत संकल्पनांशी संबंधित आहे. जर तुम्हाला सखोल अभ्यास करायचा असेल तर हा एक चांगला विषय आहे. +> येथे डेटा स्वयंचलितपणे दृश्य अद्यतनित करतो तो भाग आम्ही कव्हर करणार नाही, कारण तो [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) च्या अधिक प्रगत संकल्पनांशी संबंधित आहे. जर तुम्हाला सखोल अभ्यास करायचा असेल तर हा एक चांगला पुढील विषय आहे. -✅ स्टेट मॅनेजमेंटसाठी वेगवेगळ्या दृष्टिकोनांसह अनेक लायब्ररी उपलब्ध आहेत, [Redux](https://redux.js.org) हे एक लोकप्रिय पर्याय आहे. मोठ्या वेब अ‍ॅप्समध्ये तुम्हाला कोणत्या संभाव्य समस्या येऊ शकतात आणि त्या कशा सोडवता येतील हे शिकण्यासाठी वापरले जाणारे संकल्पना आणि पॅटर्न पाहा. +✅ स्टेट मॅनेजमेंटसाठी वेगवेगळ्या दृष्टिकोनांसह अनेक लायब्ररी उपलब्ध आहेत, [Redux](https://redux.js.org) हा एक लोकप्रिय पर्याय आहे. मोठ्या वेब अ‍ॅप्समध्ये तुम्ही कोणत्या संभाव्य समस्यांना सामोरे जाऊ शकता आणि त्या कशा सोडवता येतील हे शिकण्यासाठी वापरले जाणारे संकल्पना आणि पॅटर्न पाहा. ### कार्य -आम्ही थोडे रिफॅक्टरिंग करून सुरुवात करू. `account` डिक्लरेशन बदला: +आम्ही थोडेसे कोड पुनर्रचना करून सुरुवात करू. `account` डिक्लेरेशन बदला: ```js let account = null; ``` -सह: +यासह: ```js let state = { @@ -75,9 +75,9 @@ let state = { }; ``` -आमच्या अ‍ॅपमधील सर्व डेटा एका सिंगल स्टेट ऑब्जेक्टमध्ये *केंद्रीकृत* करण्याची कल्पना आहे. सध्या स्टेटमध्ये फक्त `account` आहे त्यामुळे फारसा बदल होत नाही, परंतु यामुळे भविष्यातील सुधारणा शक्य होतात. +कल्पना म्हणजे सर्व अ‍ॅप डेटा एका सिंगल स्टेट ऑब्जेक्टमध्ये *केंद्रीकृत* करणे. सध्या स्टेटमध्ये फक्त `account` आहे त्यामुळे फारसा फरक पडत नाही, परंतु भविष्यातील बदलांसाठी मार्ग तयार होतो. -आम्हाला ते वापरणाऱ्या फंक्शन्स देखील अपडेट कराव्या लागतील. `register()` आणि `login()` फंक्शन्समध्ये, `account = ...` बदला `state.account = ...`; +आपल्याला ते वापरणाऱ्या फंक्शन्स देखील अद्यतनित कराव्या लागतील. `register()` आणि `login()` फंक्शन्समध्ये, `account = ...` ला `state.account = ...` ने बदला; `updateDashboard()` फंक्शनच्या शीर्षस्थानी, ही ओळ जोडा: @@ -85,17 +85,17 @@ let state = { const account = state.account; ``` -या रिफॅक्टरिंगमुळे फारसे सुधारणा झाल्या नाहीत, परंतु पुढील बदलांसाठी पाया घालणे हे उद्दिष्ट होते. +या पुनर्रचनेने स्वतःहून फारसे सुधारणा केल्या नाहीत, परंतु पुढील बदलांसाठी पाया घालण्याचा विचार होता. -## डेटा बदल ट्रॅक करा +## डेटा बदलांचा मागोवा घ्या -आता आपण डेटा स्टोअर करण्यासाठी `state` ऑब्जेक्ट तयार केला आहे, पुढील पायरी म्हणजे अपडेट्स केंद्रीकृत करणे. कोणतेही बदल आणि ते कधी घडतात हे ट्रॅक करणे सोपे बनवणे हे उद्दिष्ट आहे. +आता आपण डेटा साठवण्यासाठी `state` ऑब्जेक्ट तयार केला आहे, पुढील पाऊल म्हणजे अद्यतनांना केंद्रीकृत करणे. उद्दिष्ट म्हणजे कोणतेही बदल आणि ते कधी घडतात याचा मागोवा घेणे सोपे करणे. -`state` ऑब्जेक्टमध्ये बदल होऊ नयेत यासाठी, त्याला [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) मानणे चांगली पद्धत आहे, म्हणजे त्यात अजिबात बदल करता येणार नाही. याचा अर्थ तुम्हाला त्यात काहीही बदल करायचे असल्यास नवीन स्टेट ऑब्जेक्ट तयार करावा लागेल. असे करून, तुम्ही संभाव्य अवांछित [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) पासून संरक्षण तयार करता आणि तुमच्या अ‍ॅपमध्ये नवीन वैशिष्ट्ये लागू करण्यासाठी शक्यता उघडता, जसे की undo/redo लागू करणे, तसेच डिबग करणे सोपे बनवता. उदाहरणार्थ, तुम्ही स्टेटमध्ये केलेला प्रत्येक बदल लॉग करू शकता आणि बगचा स्रोत समजण्यासाठी बदलांचा इतिहास ठेवू शकता. +`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 ऑब्जेक्टमध्ये बदल करण्याचा प्रयत्न केला तर अपवाद निर्माण होईल. +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) वाचू शकता. +✅ तुम्हाला *shallow* आणि *deep* immutable ऑब्जेक्टमधील फरक माहित आहे का? तुम्ही याबद्दल [येथे](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) वाचू शकता. ### कार्य @@ -110,9 +110,9 @@ function updateState(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` प्रॉपर्टी आहे, परंतु या दृष्टिकोनाने तुम्ही स्टेटमध्ये जितक्या प्रॉपर्टी आवश्यक आहेत तितक्या जोडू शकता. +या फंक्शनमध्ये, आम्ही नवीन स्टेट ऑब्जेक्ट तयार करतो आणि [*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` इनिशियलायझेशन देखील अपडेट करू जेणेकरून प्रारंभिक स्टेट देखील फ्रोझन असेल: +`state` प्रारंभिकरण देखील अद्यतनित करू जेणेकरून प्रारंभिक स्टेट देखील फ्रीज केले जाईल: ```js let state = Object.freeze({ @@ -120,19 +120,19 @@ let state = Object.freeze({ }); ``` -यानंतर, `register` फंक्शन अपडेट करा आणि `state.account = result;` असाइनमेंट बदला: +यानंतर, `register` फंक्शनमध्ये `state.account = result;` असाइनमेंट बदलून: ```js updateState('account', result); ``` -`login` फंक्शनसह देखील असेच करा, `state.account = data;` बदला: +`login` फंक्शनमध्ये देखील तसेच करा, `state.account = data;` बदलून: ```js updateState('account', data); ``` -आता आपण *Logout* क्लिक केल्यावर खाते डेटा साफ न होण्याच्या समस्येचे निराकरण करण्याची संधी घेऊ. +आता जेव्हा वापरकर्ता *Logout* क्लिक करतो तेव्हा खाते डेटा साफ न होण्याच्या समस्येचे निराकरण करण्याची संधी घेऊया. नवीन `logout()` फंक्शन तयार करा: @@ -143,49 +143,49 @@ function logout() { } ``` -`updateDashboard()` मध्ये, `return navigate('/login');` रीडायरेक्शन बदला `return logout();`; +`updateDashboard()` मध्ये, `return navigate('/login');` पुनर्निर्देशन बदलून `return logout();` करा; -नवीन खाते नोंदणी करा, लॉगआउट करा आणि पुन्हा लॉगिन करा आणि सर्व काही योग्य प्रकारे कार्य करत आहे का ते तपासा. +नवीन खाते नोंदणी करा, लॉगआउट करा आणि पुन्हा लॉगिन करून सर्व काही योग्यरित्या कार्यरत आहे का ते तपासा. -> टिप: तुम्ही `updateState()` च्या तळाशी `console.log(state)` जोडून आणि तुमच्या ब्राउझरच्या डेव्हलपमेंट टूल्समध्ये कन्सोल उघडून सर्व स्टेट बदल पाहू शकता. +> टीप: तुम्ही `updateState()` च्या तळाशी `console.log(state)` जोडून आणि तुमच्या ब्राउझरच्या विकास साधनांमध्ये कन्सोल उघडून सर्व स्टेट बदल पाहू शकता. ## स्टेट टिकवून ठेवा -बहुतेक वेब अ‍ॅप्सना योग्य प्रकारे कार्य करण्यासाठी डेटा टिकवून ठेवणे आवश्यक असते. सर्व महत्त्वाचा डेटा सामान्यतः डेटाबेसमध्ये संग्रहित केला जातो आणि सर्व्हर API द्वारे प्रवेश केला जातो, जसे की आमच्या बाबतीत वापरकर्ता खाते डेटा. परंतु कधीकधी, ब्राउझरमध्ये चालणाऱ्या क्लायंट अ‍ॅपवर काही डेटा टिकवून ठेवणे देखील मनोरंजक असते, चांगल्या वापरकर्ता अनुभवासाठी किंवा लोडिंग कार्यक्षमतेत सुधारणा करण्यासाठी. +बहुतेक वेब अ‍ॅप्सना योग्यरित्या कार्य करण्यासाठी डेटा टिकवून ठेवण्याची आवश्यकता असते. सर्व महत्त्वाचा डेटा सहसा डेटाबेसमध्ये संग्रहित केला जातो आणि सर्व्हर API द्वारे प्रवेश केला जातो, जसे की आमच्या बाबतीत वापरकर्ता खाते डेटा. परंतु कधीकधी, ब्राउझरमध्ये चालणाऱ्या क्लायंट अ‍ॅपवर काही डेटा टिकवून ठेवणे देखील मनोरंजक असते, चांगल्या वापरकर्ता अनुभवासाठी किंवा लोडिंग कार्यक्षमता सुधारण्यासाठी. -जेव्हा तुम्हाला तुमच्या ब्राउझरमध्ये डेटा टिकवून ठेवायचा असतो, तेव्हा तुम्ही स्वतःला काही महत्त्वाचे प्रश्न विचारले पाहिजेत: +जेव्हा तुम्हाला तुमच्या ब्राउझरमध्ये डेटा टिकवून ठेवायचा असेल, तेव्हा तुम्ही स्वतःला काही महत्त्वाचे प्रश्न विचारले पाहिजेत: -- *डेटा संवेदनशील आहे का?* तुम्ही क्लायंटवर कोणताही संवेदनशील डेटा संग्रहित करण्याचे टाळले पाहिजे, जसे की वापरकर्ता पासवर्ड. -- *तुम्हाला किती काळ हा डेटा ठेवायचा आहे?* तुम्ही हा डेटा फक्त चालू सत्रासाठी प्रवेश करण्याची योजना आखत आहात की तुम्हाला तो कायमस्वरूपी संग्रहित करायचा आहे? +- *डेटा संवेदनशील आहे का?* तुम्ही क्लायंटवर कोणताही संवेदनशील डेटा संग्रहित करणे टाळले पाहिजे, जसे की वापरकर्ता पासवर्ड. +- *तुम्हाला हा डेटा किती काळ ठेवायचा आहे?* तुम्ही हा डेटा फक्त चालू सत्रासाठी प्रवेश करण्याची योजना आखत आहात की तुम्हाला तो कायमस्वरूपी संग्रहित करायचा आहे? -वेब अ‍ॅपमध्ये माहिती संग्रहित करण्याचे अनेक मार्ग आहेत, तुम्हाला काय साध्य करायचे आहे यावर अवलंबून. उदाहरणार्थ, तुम्ही शोध क्वेरी संग्रहित करण्यासाठी URL वापरू शकता आणि ते वापरकर्त्यांमध्ये शेअर करण्यायोग्य बनवू शकता. तुम्ही [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) देखील वापरू शकता जर डेटा सर्व्हरसह शेअर करणे आवश्यक असेल, जसे की [authentication](https://en.wikipedia.org/wiki/Authentication) माहिती. +वेब अ‍ॅपमध्ये माहिती संग्रहित करण्याचे अनेक मार्ग आहेत, तुम्हाला काय साध्य करायचे आहे यावर अवलंबून. उदाहरणार्थ, तुम्ही शोध क्वेरी संग्रहित करण्यासाठी URL वापरू शकता आणि ती वापरकर्त्यांमध्ये शेअर करण्यायोग्य बनवू शकता. जर डेटा सर्व्हरसह शेअर करणे आवश्यक असेल, जसे की [authentication](https://en.wikipedia.org/wiki/Authentication) माहिती, तर तुम्ही [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) वापरू शकता. -डेटा संग्रहित करण्यासाठी अनेक ब्राउझर APIs आहेत. त्यापैकी दोन विशेषतः मनोरंजक आहेत: +ब्राउझर 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` प्रमाणेच कार्य करते परंतु यात संग्रहित डेटा सत्र संपल्यावर (ब्राउझर बंद झाल्यावर) साफ केला जातो. +- [`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` प्रमाणेच कार्य करते परंतु यात संग्रहित डेटा सत्र संपल्यावर (ब्राउझर बंद केल्यावर) साफ केला जातो. -लक्षात घ्या की या दोन्ही APIs फक्त [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) स्वरूपात सिरीयलाइझ करावे लागेल. +टीप की या दोन्ही 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) वापरून क्लायंटवर डेटाबेस तयार करणे देखील शक्य आहे. हे प्रगत उपयोग प्रकरणांसाठी किंवा तुम्हाला मोठ्या प्रमाणात डेटा संग्रहित करायचा असल्यास राखीव आहे, कारण ते वापरण्यास अधिक जटिल आहे. +✅ जर तुम्हाला सर्व्हरशिवाय कार्य करणारे वेब अ‍ॅप तयार करायचे असेल, तर [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) वापरून क्लायंटवर डेटाबेस तयार करणे देखील शक्य आहे. हे प्रगत वापर प्रकरणांसाठी राखीव आहे किंवा तुम्हाला लक्षणीय प्रमाणात डेटा संग्रहित करायचा असल्यास, कारण ते वापरण्यास अधिक जटिल आहे. ### कार्य -आम्हाला आमच्या वापरकर्त्यांना *Logout* बटणावर स्पष्टपणे क्लिक करेपर्यंत लॉग इन ठेवायचे आहे, त्यामुळे आम्ही खाते डेटा संग्रहित करण्यासाठी `localStorage` वापरू. प्रथम, आपण डेटा संग्रहित करण्यासाठी वापरण्यासाठी एक की परिभाषित करूया. +आपण इच्छितो की आमचे वापरकर्ते *Logout* बटणावर स्पष्टपणे क्लिक करेपर्यंत लॉग इन राहावे, म्हणून आम्ही `localStorage` वापरून खाते डेटा संग्रहित करू. प्रथम, आपण डेटा संग्रहित करण्यासाठी वापरण्यासाठी एक की परिभाषित करूया. ```js const storageKey = 'savedAccount'; ``` -मग `updateState()` फंक्शनच्या शेवटी ही ओळ जोडा: +यानंतर `updateState()` फंक्शनच्या शेवटी ही ओळ जोडा: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -यामुळे, वापरकर्ता खाते डेटा टिकवून ठेवला जाईल आणि आपण पूर्वी केंद्रीकृत केलेल्या सर्व स्टेट अपडेट्समुळे नेहमी अद्ययावत राहील. यामुळे आपल्याला पूर्वी केलेल्या सर्व रिफॅक्टरिंगचा फायदा मिळायला सुरुवात होते 🙂. +यामुळे, वापरकर्त्याचे खाते डेटा टिकवून ठेवले जाईल आणि आपण यापूर्वी केंद्रीकृत केलेल्या सर्व स्टेट अद्यतनांमुळे नेहमी अद्ययावत राहील. यामुळे आपल्याला केलेल्या सर्व पुनर्रचनेचा फायदा होतो 🙂. -डेटा सेव्ह केला जात असल्याने, अ‍ॅप लोड झाल्यावर तो पुनर्संचयित करण्याची काळजी घेणे देखील आवश्यक आहे. आता आपल्याकडे अधिक इनिशियलायझेशन कोड असणार आहे, त्यामुळे `app.js` च्या तळाशी असलेल्या पूर्वीच्या कोडसह नवीन `init` फंक्शन तयार करणे चांगली कल्पना असू शकते: +डेटा जतन केला जात असल्याने, अ‍ॅप लोड केल्यावर तो पुनर्संचयित करण्याची देखील काळजी घ्यावी लागेल. आता आपल्याकडे अधिक प्रारंभिक कोड असणार आहे, म्हणून `init` नावाचे नवीन फंक्शन तयार करणे चांगले होईल, ज्यामध्ये `app.js` च्या तळाशी असलेला आपला पूर्वीचा कोड देखील समाविष्ट असेल: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -येथे आम्ही सेव्ह केलेला डेटा पुनर्प्राप्त करतो आणि जर काही असेल तर आम्ही त्यानुसार स्टेट अपडेट करतो. हे *route* अपडेट करण्यापूर्वी करणे महत्त्वाचे आहे, कारण पृष्ठ अपडेट दरम्यान स्टेटवर अवलंबून असलेला कोड असू शकतो. +येथे आम्ही जतन केलेला डेटा पुनर्प्राप्त करतो आणि जर काही डेटा सापडला तर आम्ही त्यानुसार स्टेट अद्यतनित करतो. हे *रूट* अद्यतनित करण्यापूर्वी करणे महत्त्वाचे आहे, कारण पृष्ठ अद्यतनादरम्यान स्टेटवर अवलंबून असलेला कोड असू शकतो. -आम्ही *Dashboard* पृष्ठ आमच्या अ‍ॅप्लिकेशनचे डिफॉल्ट पृष्ठ बनवू शकतो, कारण आता आम्ही खाते डेटा टिकवून ठेवत आहोत. जर कोणताही डेटा सापडला नाही, तर डॅशबोर्ड लॉगिन पृष्ठावर रीडायरेक्ट करण्याची काळजी घेतो. `updateRoute()` मध्ये, फॉलबॅक `return navigate('/login');` बदला `return navigate('/dashboard');`. +आता आपण *Dashboard* पृष्ठाला आपल्या अ‍ॅप्लिकेशनचे डिफॉल्ट पृष्ठ बनवू शकतो, कारण आपण आता खाते डेटा टिकवून ठेवत आहोत. जर कोणताही डेटा सापडला नाही, तर डॅशबोर्ड *Login* पृष्ठावर पुनर्निर्देशित करण्याची काळजी घेतो. `updateRoute()` मध्ये, फॉलबॅक `return navigate('/login');` बदलून `return navigate('/dashboard');` करा. -आता अ‍ॅपमध्ये लॉगिन करा आणि पृष्ठ रिफ्रेश करण्याचा प्रयत्न करा. तुम्ही डॅशबोर्डवरच राहाल. या अपडेटसह आपण आपल्या सर्व प्रारंभिक समस्यांचे निराकरण केले आहे... +आता अ‍ॅपमध्ये लॉगिन करा आणि पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. तुम्ही डॅशबोर्डवरच राहाल. या अद्यतनासह आपण आपल्या सर्व प्रारंभिक समस्यांचे निराकरण केले आहे... -## डेटा रिफ्रेश करा +## डेटा रीफ्रेश करा -...परंतु आपण नवीन समस्या निर्माण केली असावी. ओह! +...पण आपण नवीन समस्या निर्माण केली असू शकतो. ओह! -`test` खाते वापरून डॅशबोर्डवर जा, नंतर टर्मिनलवर नवीन व्यवहार तयार करण्यासाठी हा आदेश चालवा: +`test` खाते वापरून डॅशबोर्डवर जा, नंतर टर्मिनलवर हा आदेश चालवून नवीन व्यवहार तयार करा: ```sh curl --request POST \ @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -आता ब्राउझरमध्ये डॅशबोर्ड पृष्ठ रिफ्रेश करण्याचा प्रयत्न करा. काय होते? तुम्हाला नवीन व्यवहार दिसतो का? +आता ब्राउझरमध्ये तुमचे डॅशबोर्ड पृष्ठ रीफ्रेश करण्याचा प्रयत्न करा. काय होते? तुम्हाला नवीन व्यवहार दिसतो का? -`localStorage` मुळे स्टेट अनिश्चित काळासाठी टिकवून ठेवली जाते, परंतु याचा अर्थ असा आहे की तुम्ही अ‍ॅपमधून लॉगआउट करून पुन्हा लॉगिन केल्याशिवाय ती कधीही अपडेट होत नाही! +`localStorage` मुळे स्टेट अनिश्चित काळासाठी टिकवून ठेवली जाते, परंतु याचा अर्थ असा आहे की तुम्ही अ‍ॅपमधून लॉगआउट आणि पुन्हा लॉगिन केल्याशिवाय ती कधीही अद्यतनित होत नाही! -यावर उपाय करण्यासाठी एक संभाव्य रणनीती म्हणजे डॅशबोर्ड लोड झाल्यावर प्रत्येक वेळी खाते डेटा पुन्हा लोड करणे, जेणेकरून जुना डेटा टाळता येईल. +हे टाळण्यासाठी एक संभाव्य रणनीती म्हणजे डॅशबोर्ड लोड केल्यावर प्रत्येक वेळी खाते डेटा पुन्हा लोड करणे, जेणेकरून डेटा जुना होणार नाही. ### कार्य @@ -258,31 +258,18 @@ async function refresh() { } ``` -हे खाते डेटा अपडेट करते, नंतर डॅशबोर्ड पृष्ठाच्या HTML अपडेट करण्याची काळजी घेते. हे डॅशबोर्ड route लोड झाल्यावर कॉल करणे आवश्यक आहे. route डिफिनिशन अपडेट करा: +हे खाते डेटा अद्यतनित करते, नंतर डॅशबोर्ड पृष्ठाच्या HTML चे अद्यतनित करण्याची काळजी घेते. डॅशबोर्ड रूट लोड झाल्यावर आम्हाला कॉल करायचे आहे तेच आहे. रूट +[व्याख्यानानंतरचा प्रश्नमंजूषा](https://ff-quizzes.netlify.app/web/quiz/48) -```js -const routes = { - '/login': { templateId: 'login' }, - '/dashboard': { templateId: 'dashboard', init: refresh } -}; -``` - -आता डॅशबोर्ड रिफ्रेश करण्याचा प्रयत्न करा, ते अपडेट केलेला खाते डेटा प्रदर्शित करेल. - ---- - -## 🚀 आव्हान - -आता आपण डॅशबोर्ड लोड झाल्यावर प्रत्येक वेळी खाते डेटा पुन्हा लोड करतो, तुम्हाला असे वाटते का की आपल्याला *संपूर्ण खाते* डेटा टिकवून ठेवण्याची आवश्यकता आहे? +## असाइनमेंट -`localStorage` मध्ये काय सेव्ह केले जाते आणि लोड केले जाते ते फक्त अ‍ॅप -[ट्रान्झॅक्शन जोडण्याचा संवाद लागू करा](assignment.md) +["Add transaction" संवाद लागू करा](assignment.md) -खालील उदाहरणात असाइनमेंट पूर्ण केल्यानंतरचा परिणाम दाखवला आहे: +असाइनमेंट पूर्ण केल्यानंतरचा एक उदाहरण परिणाम येथे दिला आहे: -![ट्रान्झॅक्शन जोडण्याचा संवाद दाखवणारा स्क्रीनशॉट](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.mr.png) +!["Add transaction" संवादाचे उदाहरण स्क्रीनशॉट दाखवत आहे](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.mr.png) --- **अस्वीकरण**: -हा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) चा वापर करून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरे त्रुटी किंवा अचूकतेच्या अभावाने युक्त असू शकतात. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही. \ No newline at end of file +हा दस्तऐवज AI भाषांतर सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी, कृपयास लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून निर्माण होणाऱ्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही. \ No newline at end of file diff --git a/translations/ms/7-bank-project/4-state-management/README.md b/translations/ms/7-bank-project/4-state-management/README.md index bd0851ddd..251dd7411 100644 --- a/translations/ms/7-bank-project/4-state-management/README.md +++ b/translations/ms/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# Membina Aplikasi Perbankan Bahagian 4: Konsep Pengurusan Keadaan +# Bina Aplikasi Perbankan Bahagian 4: Konsep Pengurusan Keadaan ## Kuiz Pra-Kuliah @@ -15,15 +15,15 @@ CO_OP_TRANSLATOR_METADATA: ### Pengenalan -Apabila aplikasi web berkembang, ia menjadi cabaran untuk menjejaki semua aliran data. Kod mana yang mendapatkan data, halaman mana yang menggunakannya, di mana dan bila ia perlu dikemas kini...mudah untuk berakhir dengan kod yang berselerak dan sukar untuk diselenggara. Ini terutamanya benar apabila anda perlu berkongsi data antara halaman yang berbeza dalam aplikasi anda, contohnya data pengguna. Konsep *pengurusan keadaan* sentiasa wujud dalam semua jenis program, tetapi apabila aplikasi web terus berkembang dalam kerumitan, ia kini menjadi titik utama untuk difikirkan semasa pembangunan. +Apabila aplikasi web berkembang, ia menjadi cabaran untuk menjejaki semua aliran data. Kod mana yang mendapatkan data, halaman mana yang menggunakannya, di mana dan bila ia perlu dikemas kini... mudah untuk berakhir dengan kod yang berselerak dan sukar untuk diselenggara. Ini terutamanya benar apabila anda perlu berkongsi data antara halaman yang berbeza dalam aplikasi anda, contohnya data pengguna. Konsep *pengurusan keadaan* sentiasa wujud dalam semua jenis program, tetapi apabila aplikasi web terus berkembang dalam kerumitan, ia kini menjadi titik utama yang perlu difikirkan semasa pembangunan. -Dalam bahagian terakhir ini, kita akan melihat semula aplikasi yang telah kita bina untuk memikirkan semula bagaimana keadaan diuruskan, membolehkan sokongan untuk penyegaran pelayar pada bila-bila masa, dan mengekalkan data merentasi sesi pengguna. +Dalam bahagian terakhir ini, kita akan meninjau semula aplikasi yang telah kita bina untuk memikirkan semula bagaimana keadaan diuruskan, membolehkan sokongan untuk penyegaran pelayar pada bila-bila masa, dan mengekalkan data merentasi sesi pengguna. ### Prasyarat -Anda perlu telah menyelesaikan bahagian [pengambilan data](../3-data/README.md) aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [menjalankan API pelayan](../api/README.md) secara tempatan supaya anda boleh menguruskan data akaun. +Anda perlu telah melengkapkan bahagian [pengambilan data](../3-data/README.md) aplikasi web untuk pelajaran ini. Anda juga perlu memasang [Node.js](https://nodejs.org) dan [menjalankan API pelayan](../api/README.md) secara tempatan supaya anda boleh menguruskan data akaun. -Anda boleh menguji bahawa pelayan berjalan dengan betul dengan melaksanakan arahan ini dalam terminal: +Anda boleh menguji sama ada pelayan berjalan dengan betul dengan melaksanakan perintah ini dalam terminal: ```sh curl http://localhost:5000/api @@ -32,7 +32,7 @@ curl http://localhost:5000/api --- -## Memikirkan semula pengurusan keadaan +## Fikirkan semula pengurusan keadaan Dalam [pelajaran sebelumnya](../3-data/README.md), kami memperkenalkan konsep asas keadaan dalam aplikasi kami dengan pembolehubah global `account` yang mengandungi data bank untuk pengguna yang sedang log masuk. Walau bagaimanapun, pelaksanaan semasa kami mempunyai beberapa kelemahan. Cuba segarkan halaman apabila anda berada di papan pemuka. Apa yang berlaku? @@ -40,26 +40,26 @@ Terdapat 3 isu dengan kod semasa: - Keadaan tidak dikekalkan, kerana penyegaran pelayar membawa anda kembali ke halaman log masuk. - Terdapat pelbagai fungsi yang mengubah keadaan. Apabila aplikasi berkembang, ia boleh menyukarkan untuk menjejaki perubahan dan mudah untuk terlupa mengemas kini satu. -- Keadaan tidak dibersihkan, jadi apabila anda klik pada *Logout*, data akaun masih ada walaupun anda berada di halaman log masuk. +- Keadaan tidak dibersihkan, jadi apabila anda mengklik *Logout*, data akaun masih ada walaupun anda berada di halaman log masuk. Kami boleh mengemas kini kod kami untuk menangani isu-isu ini satu persatu, tetapi ia akan mencipta lebih banyak penduaan kod dan menjadikan aplikasi lebih kompleks dan sukar untuk diselenggara. Atau kami boleh berhenti seketika dan memikirkan semula strategi kami. -> Apakah masalah yang sebenarnya kami cuba selesaikan di sini? +> Apakah masalah yang sebenarnya kita cuba selesaikan di sini? [Pengurusan keadaan](https://en.wikipedia.org/wiki/State_management) adalah tentang mencari pendekatan yang baik untuk menyelesaikan dua masalah tertentu ini: - Bagaimana untuk memastikan aliran data dalam aplikasi mudah difahami? - Bagaimana untuk memastikan data keadaan sentiasa selaras dengan antara muka pengguna (dan sebaliknya)? -Setelah anda menjaga perkara ini, sebarang isu lain yang mungkin anda hadapi mungkin telah diselesaikan atau menjadi lebih mudah untuk diperbaiki. Terdapat banyak pendekatan yang mungkin untuk menyelesaikan masalah ini, tetapi kami akan menggunakan penyelesaian biasa yang terdiri daripada **memusatkan data dan cara untuk mengubahnya**. Aliran data akan berjalan seperti ini: +Setelah anda menyelesaikan perkara ini, sebarang isu lain yang mungkin anda hadapi sama ada telah diselesaikan atau menjadi lebih mudah untuk diselesaikan. Terdapat banyak pendekatan yang mungkin untuk menyelesaikan masalah ini, tetapi kami akan menggunakan penyelesaian biasa yang terdiri daripada **memusatkan data dan cara untuk mengubahnya**. Aliran data akan berjalan seperti ini: ![Skema menunjukkan aliran data antara HTML, tindakan pengguna dan keadaan](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.ms.png) -> Kami tidak akan membincangkan di sini bahagian di mana data secara automatik mencetuskan kemas kini paparan, kerana ia berkaitan dengan konsep yang lebih maju tentang [Pengaturcaraan Reaktif](https://en.wikipedia.org/wiki/Reactive_programming). Ia adalah subjek susulan yang baik jika anda ingin mendalami. +> Kami tidak akan membincangkan bahagian di mana data secara automatik mencetuskan kemas kini paparan, kerana ia berkaitan dengan konsep lanjutan [Pengaturcaraan Reaktif](https://en.wikipedia.org/wiki/Reactive_programming). Ia adalah subjek susulan yang baik jika anda ingin mendalami. ✅ Terdapat banyak perpustakaan di luar sana dengan pendekatan yang berbeza untuk pengurusan keadaan, [Redux](https://redux.js.org) menjadi pilihan yang popular. Lihat konsep dan corak yang digunakan kerana ia sering menjadi cara yang baik untuk belajar tentang isu-isu yang mungkin anda hadapi dalam aplikasi web besar dan bagaimana ia boleh diselesaikan. -### Tugasan +### Tugas Kita akan mulakan dengan sedikit penstrukturan semula. Gantikan deklarasi `account`: @@ -75,7 +75,7 @@ let state = { }; ``` -Idea di sini adalah untuk *memusatkan* semua data aplikasi kami dalam satu objek keadaan. Buat masa ini kami hanya mempunyai `account` dalam keadaan, jadi ia tidak banyak berubah, tetapi ia mencipta laluan untuk evolusi. +Idea ini adalah untuk *memusatkan* semua data aplikasi kami dalam satu objek keadaan. Kami hanya mempunyai `account` buat masa ini dalam keadaan jadi ia tidak banyak berubah, tetapi ia mencipta laluan untuk evolusi. Kami juga perlu mengemas kini fungsi yang menggunakannya. Dalam fungsi `register()` dan `login()`, gantikan `account = ...` dengan `state.account = ...`; @@ -85,21 +85,21 @@ Di bahagian atas fungsi `updateDashboard()`, tambahkan baris ini: const account = state.account; ``` -Penstrukturan semula ini sendiri tidak membawa banyak peningkatan, tetapi idea di sini adalah untuk meletakkan asas untuk perubahan seterusnya. +Penstrukturan semula ini sendiri tidak membawa banyak penambahbaikan, tetapi idea ini adalah untuk meletakkan asas untuk perubahan seterusnya. -## Menjejaki perubahan data +## Jejak perubahan data -Sekarang kita telah meletakkan objek `state` untuk menyimpan data kita, langkah seterusnya adalah untuk memusatkan kemas kini. Tujuannya adalah untuk memudahkan menjejaki sebarang perubahan dan bila ia berlaku. +Sekarang kita telah meletakkan objek `state` untuk menyimpan data kita, langkah seterusnya adalah untuk memusatkan kemas kini. Matlamatnya adalah untuk memudahkan menjejaki sebarang perubahan dan bila ia berlaku. -Untuk mengelakkan perubahan dibuat pada objek `state`, adalah juga amalan yang baik untuk menganggapnya [*tidak boleh diubah*](https://en.wikipedia.org/wiki/Immutable_object), bermaksud ia tidak boleh diubah sama sekali. Ini juga bermaksud anda perlu mencipta objek keadaan baru jika anda ingin mengubah apa-apa di dalamnya. Dengan melakukan ini, anda membina perlindungan terhadap [kesan sampingan](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) yang berpotensi tidak diingini, dan membuka kemungkinan untuk ciri baru dalam aplikasi anda seperti melaksanakan undo/redo, sambil juga memudahkan debugging. Sebagai contoh, anda boleh log setiap perubahan yang dibuat pada keadaan dan menyimpan sejarah perubahan untuk memahami punca bug. +Untuk mengelakkan perubahan dibuat pada objek `state`, adalah juga amalan yang baik untuk menganggapnya [*tidak boleh diubah*](https://en.wikipedia.org/wiki/Immutable_object), yang bermaksud ia tidak boleh diubah sama sekali. Ini juga bermakna anda perlu mencipta objek keadaan baharu jika anda ingin mengubah apa-apa di dalamnya. Dengan melakukan ini, anda membina perlindungan terhadap [kesan sampingan](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) yang berpotensi tidak diingini, dan membuka kemungkinan untuk ciri baharu dalam aplikasi anda seperti melaksanakan undo/redo, sambil juga memudahkan penyahpepijatan. Sebagai contoh, anda boleh log setiap perubahan yang dibuat pada keadaan dan menyimpan sejarah perubahan untuk memahami punca pepijat. -Dalam JavaScript, anda boleh menggunakan [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) untuk mencipta versi tidak boleh diubah bagi objek. Jika anda cuba membuat perubahan pada objek tidak boleh diubah, pengecualian akan dinaikkan. +Dalam JavaScript, anda boleh menggunakan [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) untuk mencipta versi objek yang tidak boleh diubah. Jika anda cuba membuat perubahan pada objek yang tidak boleh diubah, pengecualian akan dinaikkan. -✅ Adakah anda tahu perbezaan antara objek tidak boleh diubah *shallow* dan *deep*? Anda boleh membacanya [di sini](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Adakah anda tahu perbezaan antara objek *shallow* dan *deep* yang tidak boleh diubah? Anda boleh membacanya [di sini](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). -### Tugasan +### Tugas -Mari kita cipta fungsi baru `updateState()`: +Mari kita cipta fungsi baharu `updateState()`: ```js function updateState(property, newData) { @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Dalam fungsi ini, kami mencipta objek keadaan baru dan menyalin data dari keadaan sebelumnya menggunakan [*operator spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Kemudian kami menimpa sifat tertentu objek keadaan dengan data baru menggunakan [notasi kurungan](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` untuk tugasan. Akhirnya, kami mengunci objek untuk mengelakkan pengubahsuaian menggunakan `Object.freeze()`. Buat masa ini kami hanya mempunyai sifat `account` yang disimpan dalam keadaan, tetapi dengan pendekatan ini anda boleh menambah sebanyak mana sifat yang anda perlukan dalam keadaan. +Dalam fungsi ini, kami mencipta objek keadaan baharu dan menyalin data daripada keadaan sebelumnya menggunakan [*operator spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Kemudian kami menimpa sifat tertentu objek keadaan dengan data baharu menggunakan [notasi kurungan](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` untuk tugasan. Akhir sekali, kami mengunci objek untuk mengelakkan pengubahsuaian menggunakan `Object.freeze()`. Buat masa ini, kami hanya mempunyai sifat `account` yang disimpan dalam keadaan, tetapi dengan pendekatan ini anda boleh menambah sebanyak mana sifat yang anda perlukan dalam keadaan. Kami juga akan mengemas kini inisialisasi `state` untuk memastikan keadaan awal juga dibekukan: @@ -132,9 +132,9 @@ Lakukan perkara yang sama dengan fungsi `login`, menggantikan `state.account = d updateState('account', data); ``` -Kami kini akan mengambil peluang untuk memperbaiki isu data akaun yang tidak dibersihkan apabila pengguna klik pada *Logout*. +Kami kini akan mengambil peluang untuk membetulkan isu data akaun yang tidak dibersihkan apabila pengguna mengklik *Logout*. -Cipta fungsi baru `logout()`: +Cipta fungsi baharu `logout()`: ```js function logout() { @@ -145,33 +145,33 @@ function logout() { Dalam `updateDashboard()`, gantikan pengalihan `return navigate('/login');` dengan `return logout()`; -Cuba daftar akaun baru, log keluar dan log masuk semula untuk memastikan semuanya masih berfungsi dengan betul. +Cuba daftar akaun baharu, log keluar dan log masuk semula untuk memastikan semuanya masih berfungsi dengan betul. -> Tip: anda boleh melihat semua perubahan keadaan dengan menambah `console.log(state)` di bahagian bawah `updateState()` dan membuka konsol dalam alat pembangunan pelayar anda. +> Petua: anda boleh melihat semua perubahan keadaan dengan menambah `console.log(state)` di bahagian bawah `updateState()` dan membuka konsol dalam alat pembangunan pelayar anda. -## Mengekalkan keadaan +## Kekalkan keadaan -Kebanyakan aplikasi web perlu mengekalkan data untuk dapat berfungsi dengan betul. Semua data kritikal biasanya disimpan dalam pangkalan data dan diakses melalui API pelayan, seperti data akaun pengguna dalam kes kami. Tetapi kadang-kadang, ia juga menarik untuk mengekalkan beberapa data pada aplikasi klien yang berjalan dalam pelayar anda, untuk pengalaman pengguna yang lebih baik atau untuk meningkatkan prestasi pemuatan. +Kebanyakan aplikasi web perlu mengekalkan data untuk dapat berfungsi dengan betul. Semua data kritikal biasanya disimpan dalam pangkalan data dan diakses melalui API pelayan, seperti data akaun pengguna dalam kes kami. Tetapi kadangkala, adalah menarik untuk mengekalkan beberapa data pada aplikasi klien yang berjalan dalam pelayar anda, untuk pengalaman pengguna yang lebih baik atau untuk meningkatkan prestasi pemuatan. Apabila anda ingin mengekalkan data dalam pelayar anda, terdapat beberapa soalan penting yang perlu anda tanyakan kepada diri sendiri: -- *Adakah data sensitif?* Anda harus mengelakkan menyimpan sebarang data sensitif pada klien, seperti kata laluan pengguna. +- *Adakah data itu sensitif?* Anda harus mengelakkan daripada menyimpan sebarang data sensitif pada klien, seperti kata laluan pengguna. - *Berapa lama anda perlu menyimpan data ini?* Adakah anda merancang untuk mengakses data ini hanya untuk sesi semasa atau adakah anda mahu ia disimpan selama-lamanya? -Terdapat pelbagai cara untuk menyimpan maklumat dalam aplikasi web, bergantung pada apa yang anda ingin capai. Sebagai contoh, anda boleh menggunakan URL untuk menyimpan pertanyaan carian, dan menjadikannya boleh dikongsi antara pengguna. Anda juga boleh menggunakan [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) jika data perlu dikongsi dengan pelayan, seperti maklumat [pengesahan](https://en.wikipedia.org/wiki/Authentication). +Terdapat pelbagai cara untuk menyimpan maklumat dalam aplikasi web, bergantung pada apa yang anda ingin capai. Sebagai contoh, anda boleh menggunakan URL untuk menyimpan pertanyaan carian, dan menjadikannya boleh dikongsi antara pengguna. Anda juga boleh menggunakan [kuki HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) jika data perlu dikongsi dengan pelayan, seperti maklumat [pengesahan](https://en.wikipedia.org/wiki/Authentication). Pilihan lain adalah menggunakan salah satu daripada banyak API pelayar untuk menyimpan data. Dua daripadanya sangat menarik: - [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): sebuah [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) yang membolehkan untuk mengekalkan data khusus untuk laman web semasa merentasi sesi yang berbeza. Data yang disimpan di dalamnya tidak pernah tamat tempoh. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): yang ini berfungsi sama seperti `localStorage` kecuali data yang disimpan di dalamnya akan dibersihkan apabila sesi tamat (apabila pelayar ditutup). +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ini berfungsi sama seperti `localStorage` kecuali data yang disimpan di dalamnya akan dipadamkan apabila sesi tamat (apabila pelayar ditutup). -Perhatikan bahawa kedua-dua API ini hanya membenarkan untuk menyimpan [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Jika anda ingin menyimpan objek kompleks, anda perlu menyusunnya ke format [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) menggunakan [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Perhatikan bahawa kedua-dua API ini hanya membenarkan untuk menyimpan [rentetan](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Jika anda ingin menyimpan objek kompleks, anda perlu menyusunnya ke format [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) menggunakan [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Jika anda ingin mencipta aplikasi web yang tidak berfungsi dengan pelayan, adalah juga mungkin untuk mencipta pangkalan data pada klien menggunakan API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Yang ini dikhaskan untuk kes penggunaan lanjutan atau jika anda perlu menyimpan sejumlah besar data, kerana ia lebih kompleks untuk digunakan. +✅ Jika anda ingin mencipta aplikasi web yang tidak berfungsi dengan pelayan, adalah juga mungkin untuk mencipta pangkalan data pada klien menggunakan API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ini dikhaskan untuk kes penggunaan lanjutan atau jika anda perlu menyimpan sejumlah besar data, kerana ia lebih kompleks untuk digunakan. -### Tugasan +### Tugas -Kami mahu pengguna kami kekal log masuk sehingga mereka secara eksplisit klik pada butang *Logout*, jadi kami akan menggunakan `localStorage` untuk menyimpan data akaun. Pertama, mari kita tentukan kunci yang akan kita gunakan untuk menyimpan data kita. +Kami mahu pengguna kami kekal log masuk sehingga mereka secara eksplisit mengklik butang *Logout*, jadi kami akan menggunakan `localStorage` untuk menyimpan data akaun. Pertama, mari kita tentukan kunci yang akan kita gunakan untuk menyimpan data kita. ```js const storageKey = 'savedAccount'; @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); Dengan ini, data akaun pengguna akan dikekalkan dan sentiasa terkini kerana kami telah memusatkan semua kemas kini keadaan kami sebelum ini. Di sinilah kami mula mendapat manfaat daripada semua penstrukturan semula kami sebelum ini 🙂. -Oleh kerana data disimpan, kami juga perlu mengambil kira pemulihannya apabila aplikasi dimuatkan. Oleh kerana kami akan mula mempunyai lebih banyak kod inisialisasi, mungkin idea yang baik untuk mencipta fungsi baru `init`, yang juga termasuk kod kami sebelum ini di bahagian bawah `app.js`: +Memandangkan data disimpan, kami juga perlu mengambil berat tentang memulihkannya apabila aplikasi dimuatkan. Oleh kerana kami akan mula mempunyai lebih banyak kod inisialisasi, mungkin idea yang baik untuk mencipta fungsi baharu `init`, yang juga termasuk kod kami sebelum ini di bahagian bawah `app.js`: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -Di sini kami mengambil data yang disimpan, dan jika ada, kami mengemas kini keadaan sewajarnya. Adalah penting untuk melakukan ini *sebelum* mengemas kini laluan, kerana mungkin terdapat kod yang bergantung pada keadaan semasa kemas kini halaman. +Di sini kami mendapatkan data yang disimpan, dan jika ada, kami mengemas kini keadaan sewajarnya. Adalah penting untuk melakukan ini *sebelum* mengemas kini laluan, kerana mungkin terdapat kod yang bergantung pada keadaan semasa kemas kini halaman. -Kami juga boleh menjadikan halaman *Dashboard* sebagai halaman lalai aplikasi kami, kerana kami kini mengekalkan data akaun. Jika tiada data ditemui, papan pemuka akan menguruskan pengalihan ke halaman *Login* pula. Dalam `updateRoute()`, gantikan fallback `return navigate('/login');` dengan `return navigate('/dashboard');`. +Kami juga boleh menjadikan halaman *Dashboard* sebagai halaman lalai aplikasi kami, kerana kami kini mengekalkan data akaun. Jika tiada data ditemui, papan pemuka akan menguruskan pengalihan ke halaman *Login* juga. Dalam `updateRoute()`, gantikan fallback `return navigate('/login');` dengan `return navigate('/dashboard');`. -Sekarang log masuk ke aplikasi dan cuba segarkan halaman. Anda sepatutnya kekal di papan pemuka. Dengan kemas kini itu, kami telah menjaga semua isu awal kami... +Sekarang log masuk ke aplikasi dan cuba segarkan halaman. Anda sepatutnya kekal di papan pemuka. Dengan kemas kini itu, kami telah menyelesaikan semua isu awal kami... -## Menyegarkan data +## Segarkan data -...Tetapi kami mungkin juga telah mencipta isu baru. Oops! +...Tetapi kami mungkin juga telah mencipta isu baharu. Oops! -Pergi ke papan pemuka menggunakan akaun `test`, kemudian jalankan arahan ini pada terminal untuk mencipta transaksi baru: +Pergi ke papan pemuka menggunakan akaun `test`, kemudian jalankan perintah ini pada terminal untuk mencipta transaksi baharu: ```sh curl --request POST \ @@ -221,15 +221,15 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Cuba segarkan halaman papan pemuka anda dalam pelayar sekarang. Apa yang berlaku? Adakah anda melihat transaksi baru? +Cuba segarkan halaman papan pemuka anda dalam pelayar sekarang. Apa yang berlaku? Adakah anda melihat transaksi baharu? -Keadaan dikekalkan tanpa had terima kasih kepada `localStorage`, tetapi itu juga bermaksud ia tidak pernah dikemas kini sehingga anda log keluar dari aplikasi dan log masuk semula! +Keadaan dikekalkan selama-lamanya terima kasih kepada `localStorage`, tetapi itu juga bermakna ia tidak pernah dikemas kini sehingga anda log keluar dari aplikasi dan log masuk semula! -Satu strategi yang mungkin untuk memperbaikinya adalah dengan memuat semula data akaun setiap kali papan pemuka dimuatkan, untuk mengelakkan data yang tidak terkini. +Satu strategi yang mungkin untuk membetulkannya adalah dengan memuat semula data akaun setiap kali papan pemuka dimuatkan, untuk mengelakkan data yang tidak terkini. -### Tugasan +### Tugas -Cipta fungsi baru `updateAccountData`: +Cipta fungsi baharu `updateAccountData`: ```js async function updateAccountData() { @@ -249,7 +249,7 @@ async function updateAccountData() { Kaedah ini memeriksa bahawa kami sedang log masuk kemudian memuat semula data akaun dari pelayan. -Cipta fungsi lain bernama `refresh`: +Cipta satu lagi fungsi bernama `refresh`: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -Yang ini mengemas kini data akaun, kemudian menguruskan kemas kini HTML halaman papan pemuka. Ia adalah apa yang perlu kita panggil apabila laluan papan pemuka dimuatkan. Kemas kini definisi laluan dengan: +Yang ini mengemas kini data akaun, kemudian menguruskan pengemaskinian HTML halaman papan pemuka. Inilah yang perlu kita panggil apabila laluan papan pemuka dimuatkan. Kemas kini definisi laluan dengan: ```js const routes = { @@ -273,22 +273,22 @@ Cuba muat semula papan pemuka sekarang, ia sepatutnya memaparkan data akaun yang ## 🚀 Cabaran -Sekarang kita memuat semula data akaun setiap kali papan pemuka dimuatkan, adakah anda fikir kita masih perlu mengekalkan *semua data akaun*? +Sekarang bahawa kami memuat semula data akaun setiap kali papan pemuka dimuatkan, adakah anda fikir kami masih perlu mengekalkan *semua data akaun*? Cuba bekerjasama untuk mengubah apa yang disimpan dan dimuatkan dari `localStorage` untuk hanya memasukkan apa yang benar-benar diperlukan untuk aplikasi berfungsi. ## Kuiz Pasca-Kuliah - -[Kuiz pasca-kuliah](https://ff-quizzes.netlify.app/web/quiz/48) +[Kuiz selepas kuliah](https://ff-quizzes.netlify.app/web/quiz/48) ## Tugasan -[Melaksanakan dialog "Tambah transaksi"](assignment.md) -Berikut adalah contoh hasil selepas melengkapkan tugasan: +[Laksanakan dialog "Tambah transaksi"](assignment.md) + +Berikut adalah contoh hasil selepas menyelesaikan tugasan: ![Tangkapan skrin menunjukkan contoh dialog "Tambah transaksi"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.ms.png) --- **Penafian**: -Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Walaupun kami berusaha untuk memastikan ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat yang kritikal, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini. \ No newline at end of file +Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI [Co-op Translator](https://github.com/Azure/co-op-translator). Walaupun kami berusaha untuk memastikan ketepatan, sila ambil perhatian bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang berwibawa. Untuk maklumat yang kritikal, terjemahan manusia profesional adalah disyorkan. Kami tidak bertanggungjawab atas sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini. \ No newline at end of file diff --git a/translations/my/7-bank-project/4-state-management/README.md b/translations/my/7-bank-project/4-state-management/README.md index ef4876b60..6e8eaf332 100644 --- a/translations/my/7-bank-project/4-state-management/README.md +++ b/translations/my/7-bank-project/4-state-management/README.md @@ -1,27 +1,29 @@ -# ဘဏ်လုပ်ငန်းအက်ပ် တည်ဆောက်ခြင်း အပိုင်း ၄: အခြေအနေ စီမံခန့်ခွဲမှု၏ အယူအဆများ +# ဘဏ်လုပ်ငန်းအက်ပ်တည်ဆောက်ခြင်း အပိုင်း ၄: အခြေအနေစီမံခန့်ခွဲမှု၏ အယူအဆများ -## မိန့်ခွန်းမတိုင်မီ မေးခွန်းများ +## မိန့်ခွန်းမတိုင်မီမေးခွန်းများ -[မိန့်ခွန်းမတိုင်မီ မေးခွန်းများ](https://ff-quizzes.netlify.app/web/quiz/47) +[မိန့်ခွန်းမတိုင်မီမေးခွန်းများ](https://ff-quizzes.netlify.app/web/quiz/47) ### အကျဉ်းချုပ် -ဝက်ဘ်အက်ပ်တစ်ခု ကြီးထွားလာသည့်အခါ၊ ဒေတာများကို စီမံခန့်ခွဲရန် အခက်အခဲများ ဖြစ်လာနိုင်သည်။ ဘယ်ကုဒ်က ဒေတာကို ရယူသလဲ၊ ဘယ်စာမျက်နှာက ဒေတာကို သုံးစွဲသလဲ၊ ဘယ်နေရာမှာ၊ ဘယ်အချိန်မှာ ဒေတာကို ပြန်လည် အပ်ဒိတ်လုပ်ရမလဲ... အလွယ်တကူ စီမံခန့်ခွဲရန် ခက်ခဲသော ကုဒ်များဖြစ်လာနိုင်သည်။ အထူးသဖြင့် သင့်အက်ပ်၏ စာမျက်နှာများအကြား ဒေတာများကို မျှဝေရန် လိုအပ်သောအခါ၊ ဥပမာအားဖြင့် အသုံးပြုသူ၏ ဒေတာကို မျှဝေလိုသောအခါ၊ *state management* (အခြေအနေ စီမံခန့်ခွဲမှု) ဆိုသည့် အယူအဆသည် အစဉ်အမြဲ ရှိနေခဲ့ပြီး၊ ဝက်ဘ်အက်ပ်များ ကြီးထွားလာသည့်အခါ၊ အရေးပါသော အချက်တစ်ခုအဖြစ် ဖွံ့ဖြိုးတိုးတက်မှုအတွင်းတွင် စဉ်းစားရန် လိုအပ်လာသည်။ +ဝက်ဘ်အက်ပ်တစ်ခုကြီးထွားလာသည့်အခါ၊ ဒေတာများကိုစီမံခန့်ခွဲရန်အခက်အခဲဖြစ်လာနိုင်သည်။ ဘယ်ကုဒ်ကဒေတာကိုရယူသလဲ၊ ဘယ်စာမျက်နှာကအသုံးပြုသလဲ၊ ဘယ်နေရာမှာနှင့်ဘယ်အချိန်မှာ update လုပ်ဖို့လိုအပ်သလဲ... ကုဒ်များရောထွေးပြီး ထိန်းသိမ်းရန်ခက်ခဲလာနိုင်သည်။ အထူးသဖြင့် app ရဲ့အမျိုးမျိုးသောစာမျက်နှာများအကြား ဒေတာများကိုမျှဝေဖို့လိုအပ်တဲ့အခါမှာ၊ ဥပမာအားဖြင့် အသုံးပြုသူဒေတာများ။ *State management* ဆိုတဲ့အယူအဆက အမျိုးမျိုးသောပရိုဂရမ်များမှာ အမြဲရှိနေခဲ့ပေမယ့်၊ ဝက်ဘ်အက်ပ်များက ပိုမိုရှုပ်ထွေးလာတာနဲ့အမျှ ဒီအချက်ကို ဖွံ့ဖြိုးတိုးတက်မှုအတွင်းတွင် အရေးကြီးသောအချက်အနေဖြင့်စဉ်းစားဖို့လိုလာပါတယ်။ -ဒီအပိုင်းနောက်ဆုံးတွင်၊ သင့်အက်ပ်ကို ပြန်လည်စဉ်းစားပြီး state ကို စီမံခန့်ခွဲပုံကို ပြောင်းလဲကြည့်မည်ဖြစ်ပြီး၊ ဘရောက်ဆာကို မည်သည့်အချိန်တွင်မဆို refresh လုပ်နိုင်ရန်နှင့် အသုံးပြုသူ session များအကြား ဒေတာကို ထိန်းသိမ်းထားနိုင်ရန် အထောက်အပံ့ပေးမည်ဖြစ်သည်။ +ဒီအပိုင်းနောက်ဆုံးမှာတော့၊ state ကိုဘယ်လိုစီမံခန့်ခွဲရမလဲဆိုတာကို ပြန်လည်စဉ်းစားပြီး၊ ဘရောက်ဇာကို refresh လုပ်တဲ့အချိန်မှာမည်သည့်အချိန်တွင်မဆိုထောက်ခံနိုင်ရန်နှင့် အသုံးပြုသူ session များအကြား ဒေတာများကိုတည်ရှိနေစေဖို့အတွက် app ကိုပြန်လည်ကြည့်ရှုပါမည်။ ### ကြိုတင်လိုအပ်ချက် -ဒီသင်ခန်းစာအတွက် [data fetching](../3-data/README.md) အပိုင်းကို ပြီးစီးထားရန် လိုအပ်သည်။ [Node.js](https://nodejs.org) ကို install လုပ်ပြီး [server API](../api/README.md) ကို locally run လုပ်ရန် လိုအပ်သည်။ သင့်အကောင့်ဒေတာကို စီမံခန့်ခွဲနိုင်ရန် server ကို run လုပ်ထားသည်ကို terminal မှာ အောက်ပါ command ကို အသုံးပြု၍ စမ်းသပ်နိုင်သည်။ +ဒီသင်ခန်းစာအတွက် [data fetching](../3-data/README.md) အပိုင်းကိုပြီးစီးထားဖို့လိုအပ်ပါတယ်။ [Node.js](https://nodejs.org) ကို install လုပ်ပြီး [server API](../api/README.md) ကို locally run လုပ်ဖို့လည်းလိုအပ်ပါတယ်၊ ဒါမှ account data ကိုစီမံခန့်ခွဲနိုင်ပါမယ်။ + +Server ကအဆင်ပြေစွာ run လုပ်နေတယ်ဆိုတာကို terminal မှာ ဒီ command ကို run လုပ်ပြီးစစ်ဆေးနိုင်ပါတယ်- ```sh curl http://localhost:5000/api @@ -30,36 +32,33 @@ curl http://localhost:5000/api --- -## အခြေအနေ စီမံခန့်ခွဲမှုကို ပြန်လည်စဉ်းစားခြင်း - -[ယခင်သင်ခန်းစာ](../3-data/README.md) တွင်၊ global `account` variable ကို အသုံးပြု၍ လက်ရှိ login လုပ်ထားသော အသုံးပြုသူ၏ ဘဏ်ဒေတာကို ထည့်သွင်းထားသော state အခြေခံအယူအဆကို မိတ်ဆက်ခဲ့သည်။ သို့သော်လည်း၊ လက်ရှိ implementation တွင် အချို့သော အားနည်းချက်များ ရှိနေသည်။ Dashboard တွင် refresh လုပ်ကြည့်ပါ။ ဘာဖြစ်သလဲ? +## State management ကိုပြန်လည်စဉ်းစားခြင်း -လက်ရှိကုဒ်တွင် အခက်အခဲ ၃ ခု ရှိသည်- +[ယခင်သင်ခန်းစာ](../3-data/README.md) မှာ၊ global `account` variable ကိုအသုံးပြုပြီး လက်ရှိ login လုပ်ထားတဲ့အသုံးပြုသူရဲ့ဘဏ်ဒေတာကိုထည့်သွင်းထားတဲ့ app ရဲ့ state အခြေခံအယူအဆကိုမိတ်ဆက်ပေးခဲ့ပါတယ်။ သို့သော်လည်း၊ လက်ရှိ implementation မှာအချို့အခက်အခဲများရှိပါတယ်။ Dashboard မှာရှိနေတဲ့အချိန်မှာစာမျက်နှာကို refresh လုပ်ကြည့်ပါ။ ဘာဖြစ်သွားလဲ? -- state ကို ထိန်းသိမ်းထားခြင်းမရှိသဖြင့် browser refresh လုပ်လိုက်သည်နှင့် login စာမျက်နှာသို့ ပြန်သွားသည်။ -- state ကို ပြောင်းလဲသည့် function များစွာ ရှိသည်။ အက်ပ်ကြီးလာသည်နှင့် အပြောင်းအလဲများကို စဉ်းစားရန် ခက်ခဲလာပြီး function တစ်ခုကို အပ်ဒိတ်လုပ်ရန် မေ့နိုင်သည်။ -- state ကို သန့်ရှင်းမလုပ်သဖြင့် *Logout* ကို နှိပ်လိုက်သည်နှင့် login စာမျက်နှာတွင် ရောက်နေသော်လည်း account data သေးသေးလေး ရှိနေသည်။ +လက်ရှိကုဒ်မှာ ၃ ခုသောပြဿနာများရှိပါတယ်- -ဒီအခက်အခဲများကို တစ်ခုချင်းစီ ဖြေရှင်းရန် ကုဒ်ကို update လုပ်နိုင်သော်လည်း၊ ကုဒ်များ ထပ်တူထပ်မျှဖြစ်လာပြီး အက်ပ်ကို စီမံခန့်ခွဲရန် ခက်ခဲလာနိုင်သည်။ ဒါမှမဟုတ်၊ အနည်းငယ် ခေတ္တရပ်ပြီး မိမိ၏ strategy ကို ပြန်လည်စဉ်းစားနိုင်သည်။ +- State ကိုတည်ရှိနေစေမထားပါဘူး၊ ဘရောက်ဇာကို refresh လုပ်တဲ့အခါ login စာမျက်နှာကိုပြန်သွားပါတယ်။ +- State ကိုပြောင်းလဲစေတဲ့ function များစွာရှိပါတယ်။ App ကြီးလာတာနဲ့အမျှ၊ ဒါကပြောင်းလဲမှုများကိုစစ်ဆေးဖို့ခက်ခဲစေပြီး တစ်ခုခုကို update လုပ်ဖို့မေ့လို့ဖြစ်နိုင်ပါတယ်။ +- State ကိုရှင်းလင်းမလုပ်ပါဘူး၊ ဒါကြောင့် *Logout* ကိုနှိပ်တဲ့အခါ login စာမျက်နှာမှာရှိနေတဲ့အချိန်မှာတောင် account data ကအဲဒီမှာရှိနေဆဲဖြစ်ပါတယ်။ -> ဒီအခက်အခဲများကို အမှန်တကယ် ဖြေရှင်းရန် ဘာတွေကို စဉ်းစားရမလဲ? +ဒီပြဿနာတွေကိုတစ်ခုချင်း update လုပ်ဖို့အစား၊ အချိန်အနည်းငယ်ယူပြီး မိမိရဲ့နည်းလမ်းကိုပြန်လည်စဉ်းစားနိုင်ပါတယ်။ -[State management](https://en.wikipedia.org/wiki/State_management) ဆိုတာ အက်ပ်တစ်ခုတွင် အောက်ပါ ၂ ချက်ကို ဖြေရှင်းရန် အကောင်းဆုံးနည်းလမ်းကို ရှာဖွေခြင်းဖြစ်သည်- +> ဒီမှာအမှန်တကယ်ဖြေရှင်းဖို့ကြိုးစားနေတဲ့ပြဿနာတွေကဘာလဲ? -- အက်ပ်တွင် ဒေတာများကို နားလည်ရန် လွယ်ကူစေရန် ဘယ်လိုလုပ်မလဲ? -- state data ကို အသုံးပြုသူ interface နှင့် အမြဲအချိန်တိုင်အောင် (vice versa) ဘယ်လို sync လုပ်မလဲ? +[State management](https://en.wikipedia.org/wiki/State_management) ဆိုတာ app ရဲ့ data flow တွေကိုနားလည်ရလွယ်ကူတဲ့နည်းလမ်းကိုရှာဖွေဖို့နှင့် state data ကိုအသုံးပြုသူ interface နဲ့အမြဲတန်းအညီအမျှထားဖို့ (နှင့်အတူတူ) ဘယ်လိုလုပ်ရမလဲဆိုတာကိုအဓိကထားတဲ့အရာဖြစ်ပါတယ်။ -ဒီအချက်များကို ပြုလုပ်ပြီးပါက၊ သင်ရရှိနိုင်သော အခြားသော အခက်အခဲများသည် အတော်များများ ဖြေရှင်းပြီးဖြစ်နိုင်သည်။ ဒါမှမဟုတ်၊ ဖြေရှင်းရန် ပိုမိုလွယ်ကူလာနိုင်သည်။ ဒီအခက်အခဲများကို ဖြေရှင်းရန် နည်းလမ်းများစွာ ရှိသော်လည်း၊ **ဒေတာနှင့် ဒေတာကို ပြောင်းလဲရန် နည်းလမ်းများကို အလယ်တွင် စုစည်းထားခြင်း** ဆိုသည့် နည်းလမ်းကို အသုံးပြုမည်ဖြစ်သည်။ ဒေတာများ၏ လှိုင်းများသည် အောက်ပါအတိုင်း ဖြစ်မည်- +ဒီအချက်တွေကိုစီမံခန့်ခွဲပြီးပြီဆိုရင်၊ မိမိရဲ့ app မှာရှိနေနိုင်တဲ့အခြားပြဿနာတွေဟာ အရင်ကတည်းကဖြေရှင်းပြီးသားဖြစ်နိုင်ပါတယ်၊ ဒါမှမဟုတ် ဖြေရှင်းဖို့ပိုမိုလွယ်ကူလာနိုင်ပါတယ်။ ဒီပြဿနာတွေကိုဖြေရှင်းဖို့နည်းလမ်းများစွာရှိပေမယ့်၊ **ဒေတာနှင့် ဒေတာကိုပြောင်းလဲစေတဲ့နည်းလမ်းများကိုအလယ်တွင်စုစည်းခြင်း** ဆိုတဲ့နည်းလမ်းကိုအသုံးပြုပါမယ်။ Data flow တွေကဒီလိုဖြစ်ပါမယ်- -![HTML, user actions နှင့် state အကြား ဒေတာလှိုင်းများကို ပြသသည့် schema](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.my.png) +![HTML, user actions နှင့် state အကြား data flow တွေကိုပြသတဲ့ schema](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.my.png) -> ဒီနေရာတွင် view update ကို အလိုအလျောက် trigger လုပ်သည့် အပိုင်းကို မဖော်ပြပါ၊ အကြောင်းမှာ [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) ဆိုသည့် အဆင့်မြင့်အယူအဆများနှင့် ဆက်စပ်နေသောကြောင့် ဖြစ်သည်။ အနက်ရှိုင်းစွာ လေ့လာလိုပါက အကောင်းဆုံးအကြောင်းအရာတစ်ခုဖြစ်သည်။ +> ဒီမှာ data က view ကိုအလိုအလျောက် update လုပ်စေတဲ့အပိုင်းကိုမဖော်ပြပါဘူး၊ ဒါက [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) ရဲ့ပိုမိုရှုပ်ထွေးတဲ့အယူအဆတွေနဲ့ဆက်စပ်နေပါတယ်။ အနက်ရှိုင်းစွာလေ့လာချင်ရင်တော့ ဒီအကြောင်းအရာကိုဆက်လက်လေ့လာနိုင်ပါတယ်။ -✅ State management အတွက် library များစွာ ရှိပြီး၊ [Redux](https://redux.js.org) သည် လူကြိုက်များသော ရွေးချယ်မှုတစ်ခုဖြစ်သည်။ အကြီးမားသော ဝက်ဘ်အက်ပ်များတွင် ကြုံရနိုင်သော အခက်အခဲများနှင့် ဖြေရှင်းနိုင်သော နည်းလမ်းများကို သင်ယူရန် concept များနှင့် pattern များကို ကြည့်ရှုပါ။ +✅ State management အတွက်နည်းလမ်းအမျိုးမျိုးနဲ့ library တွေများစွာရှိပါတယ်၊ [Redux](https://redux.js.org) ကလူကြိုက်များတဲ့ရွေးချယ်မှုတစ်ခုဖြစ်ပါတယ်။ အကြီးမားတဲ့ဝက်ဘ်အက်ပ်တွေမှာဖြစ်နိုင်တဲ့ပြဿနာတွေကိုဘယ်လိုဖြေရှင်းနိုင်မလဲဆိုတာကိုလေ့လာဖို့အကောင်းဆုံးနည်းလမ်းတစ်ခုအဖြစ် concept တွေနဲ့ pattern တွေကိုကြည့်ရှုပါ။ -### လုပ်ငန်း +### Task -အနည်းငယ် refactoring ဖြင့် စတင်မည်။ `account` ကို အောက်ပါအတိုင်း ပြောင်းလဲပါ- +Refactoring အနည်းငယ်နဲ့စတင်ပါမယ်။ `account` ကိုအောက်ပါအတိုင်းအစားပြောင်းပါ- ```js let account = null; @@ -73,31 +72,31 @@ let state = { }; ``` -ဒီအယူအဆမှာ *state object* တစ်ခုတွင် အက်ပ်၏ ဒေတာအားလုံးကို စုစည်းထားရန် ဖြစ်သည်။ လက်ရှိ state တွင် `account` သာ ရှိသည့်အတွက် အများကြီး မပြောင်းလဲသော်လည်း၊ အနာဂတ်အတွက် လမ်းကြောင်းတစ်ခု ဖန်တီးပေးသည်။ +အဓိကအကြောင်းအရာက app ရဲ့ data အားလုံးကို state object တစ်ခုထဲမှာစုစည်းဖို့ဖြစ်ပါတယ်။ လက်ရှိမှာ state မှာ `account` တစ်ခုသာရှိတာကြောင့် များစွာပြောင်းလဲမှုမရှိပါဘူး၊ ဒါပေမယ့်အနာဂတ်အတွက်လမ်းကြောင်းဖန်တီးပေးပါတယ်။ -ဒါ့အပြင်၊ function များကို update လုပ်ရန် လိုအပ်သည်။ `register()` နှင့် `login()` function များတွင် `account = ...` ကို `state.account = ...` ဖြင့် အစားထိုးပါ။ +ဒါ့အပြင်၊ ဒါကိုအသုံးပြုတဲ့ function တွေကိုလည်း update လုပ်ဖို့လိုအပ်ပါတယ်။ `register()` နှင့် `login()` function တွေမှာ `account = ...` ကို `state.account = ...` နဲ့အစားထိုးပါ။ -`updateDashboard()` function ၏ အပေါ်တွင် အောက်ပါလိုင်းကို ထည့်ပါ- +`updateDashboard()` function ရဲ့အပေါ်ဆုံးမှာ ဒီလိုလိုင်းတစ်ခုထည့်ပါ- ```js const account = state.account; ``` -ဒီ refactoring ကိုယ်တိုင်က အများကြီး တိုးတက်မှု မဖြစ်ပေမယ့်၊ နောက်ထပ် ပြောင်းလဲမှုများအတွက် အခြေခံအုတ်မြစ်ကို ဖန်တီးရန် ရည်ရွယ်သည်။ +ဒီ refactoring ကိုလုပ်တာနဲ့အတူ အများကြီးတိုးတက်မှုမရရှိခဲ့ပေမယ့်၊ အနာဂတ်အတွက်အခြေခံအုတ်မြစ်တစ်ခုကိုဖန်တီးဖို့ရည်ရွယ်ခဲ့တာပါ။ -## ဒေတာပြောင်းလဲမှုများကို စောင့်ကြည့်ခြင်း +## ဒေတာပြောင်းလဲမှုများကိုစစ်ဆေးခြင်း -state object ကို ဒေတာသိမ်းဆည်းရန် အသုံးပြုပြီးနောက်၊ နောက်တစ်ဆင့်မှာ update များကို စုစည်းထားရန် ဖြစ်သည်။ အပြောင်းအလဲများနှင့် အချိန်ကို စောင့်ကြည့်ရန် ပိုမိုလွယ်ကူစေရန် ရည်ရွယ်သည်။ +State object ကို data ကိုသိမ်းဆည်းဖို့အသုံးပြုထားပြီးနောက်၊ ပြောင်းလဲမှုများကိုစုစည်းဖို့နောက်တစ်ဆင့်အဆင့်တက်ပါမယ်။ ပြောင်းလဲမှုများနှင့်အချိန်ကိုလွယ်ကူစွာစစ်ဆေးနိုင်ဖို့ရည်ရွယ်ပါတယ်။ -state object ကို ပြောင်းလဲမှုများ မဖြစ်စေရန် [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) အဖြစ် စဉ်းစားရန် သင့်တော်သည်။ ဒါက state object ကို ပြောင်းလဲလို့ မရဘဲ၊ state object အသစ်တစ်ခု ဖန်တီးရန် လိုအပ်သည်။ ဒီလိုလုပ်ခြင်းဖြင့် မလိုလားအပ်သော [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) များကို ကာကွယ်ပေးပြီး၊ undo/redo ကို အကောင်အထည်ဖော်ခြင်းကဲ့သို့သော feature အသစ်များကို အက်ပ်တွင် ထည့်သွင်းနိုင်သည်။ ထို့အပြင်၊ debug လုပ်ရန် ပိုမိုလွယ်ကူစေသည်။ ဥပမာအားဖြင့်၊ state ပြောင်းလဲမှုများအားလုံးကို log လုပ်ပြီး၊ bug ရှိနေသော အရင်းအမြစ်ကို နားလည်ရန် ပြောင်းလဲမှုများ၏ သမိုင်းကို သိမ်းဆည်းနိုင်သည်။ +State object ကိုပြောင်းလဲမှုများမဖြစ်စေဖို့၊ [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) အဖြစ်စဉ်းစားဖို့ကောင်းတဲ့အလေ့အကျင့်တစ်ခုဖြစ်ပါတယ်၊ ဒါဟာ state object ကိုအလုံးစုံပြောင်းလဲမရနိုင်ပါဘူး။ ဒါက unwanted [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) မဖြစ်စေဖို့ကာကွယ်မှုတစ်ခုကိုတည်ဆောက်ပေးပြီး၊ undo/redo ကိုအကောင်အထည်ဖော်ခြင်းလိုမျိုး app ရဲ့ features အသစ်များကိုတိုးချဲ့ဖို့လမ်းဖွင့်ပေးပါတယ်၊ debugging လုပ်ဖို့လည်းပိုမိုလွယ်ကူစေပါတယ်။ ဥပမာအားဖြင့်၊ state ကိုပြောင်းလဲမှုတိုင်းကို log လုပ်ပြီး bug ရဲ့အရင်းအမြစ်ကိုနားလည်ဖို့ပြောင်းလဲမှုများရဲ့သမိုင်းကိုသိမ်းဆည်းနိုင်ပါတယ်။ -JavaScript တွင် [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) ကို အသုံးပြု၍ object တစ်ခု၏ immutable version ကို ဖန်တီးနိုင်သည်။ immutable object ကို ပြောင်းလဲရန် ကြိုးစားပါက exception တစ်ခု ထွက်လာမည်။ +JavaScript မှာ [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) ကိုအသုံးပြုပြီး object တစ်ခုရဲ့ immutable version ကိုဖန်တီးနိုင်ပါတယ်။ Immutable object ကိုပြောင်းလဲဖို့ကြိုးစားရင် exception တစ်ခုထွက်ပါမယ်။ -✅ *shallow* immutable object နှင့် *deep* immutable object တစ်ခု၏ ကွာခြားချက်ကို သိပါသလား? [ဒီနေရာ](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) တွင် ဖတ်ရှုနိုင်သည်။ +✅ *shallow* immutable object နဲ့ *deep* immutable object ရဲ့ကွာခြားချက်ကိုသိပါသလား? [ဒီမှာ](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) ဖတ်ရှုနိုင်ပါတယ်။ -### လုပ်ငန်း +### Task -`updateState()` function အသစ်တစ်ခု ဖန်တီးပါ- +`updateState()` function အသစ်တစ်ခုဖန်တီးပါ- ```js function updateState(property, newData) { @@ -108,9 +107,9 @@ function updateState(property, newData) { } ``` -ဒီ function တွင်၊ state object အသစ်တစ်ခု ဖန်တီးပြီး၊ [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) ကို အသုံးပြု၍ ယခင် state မှ ဒေတာကို ကူးယူသည်။ ထို့နောက်၊ [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` ကို အသုံးပြု၍ state object ၏ အထူး property တစ်ခုကို override လုပ်သည်။ နောက်ဆုံးတွင် `Object.freeze()` ကို အသုံးပြု၍ object ကို lock လုပ်သည်။ state တွင် လက်ရှိ `account` property သာ ရှိသော်လည်း၊ ဒီနည်းလမ်းဖြင့် state တွင် လိုအပ်သည့် property များစွာ ထည့်သွင်းနိုင်သည်။ +ဒီ function မှာ၊ [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals) ကိုအသုံးပြုပြီး state object အသစ်တစ်ခုကိုဖန်တီးပြီး၊ ယခင် state မှ data ကို copy လုပ်ပါတယ်။ ထို့နောက် state object ရဲ့ property တစ်ခုကို [bracket notation](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` ကိုအသုံးပြုပြီး override လုပ်ပါတယ်။ နောက်ဆုံးမှာ `Object.freeze()` ကိုအသုံးပြုပြီး object ကို lock လုပ်ပါတယ်။ လက်ရှိမှာ state မှာ `account` property တစ်ခုသာရှိပေမယ့်၊ ဒီနည်းလမ်းနဲ့ state မှာလိုအပ်သလို property တွေထည့်နိုင်ပါတယ်။ -state initialization ကို update လုပ်ပြီး၊ initial state ကိုလည်း freeze လုပ်ထားရန် သေချာပါ- +State initialization ကိုလည်း update လုပ်ပြီး initial state ကိုလည်း freeze လုပ်ထားဖို့သေချာစေပါ- ```js let state = Object.freeze({ @@ -118,21 +117,21 @@ let state = Object.freeze({ }); ``` -ထို့နောက်၊ `register` function တွင် `state.account = result;` assignment ကို အစား- +ထို့နောက်၊ `register` function ကို update လုပ်ပြီး `state.account = result;` assignment ကိုအစားထိုးပါ- ```js updateState('account', result); ``` -`login` function တွင်လည်း `state.account = data;` ကို အစား- +`login` function ကိုလည်းအတူတူ update လုပ်ပြီး `state.account = data;` ကိုအစားထိုးပါ- ```js updateState('account', data); ``` -အခုတော့ *Logout* ကို နှိပ်လိုက်သည်နှင့် အသုံးပြုသူ၏ account data များကို ဖယ်ရှားရန် ပြဿနာကို ဖြေရှင်းရန် အခွင့်အရေးရရှိပါပြီ။ +အခုတော့ *Logout* ကိုနှိပ်တဲ့အခါ အသုံးပြုသူရဲ့ account data ကိုရှင်းလင်းမလုပ်တဲ့ပြဿနာကိုဖြေရှင်းဖို့အခွင့်အရေးရရှိပါပြီ။ -`logout()` function အသစ်တစ်ခု ဖန်တီးပါ- +`logout()` function အသစ်တစ်ခုဖန်တီးပါ- ```js function logout() { @@ -141,56 +140,58 @@ function logout() { } ``` -`updateDashboard()` တွင် `return navigate('/login');` redirection ကို `return logout();` ဖြင့် အစားထိုးပါ။ +`updateDashboard()` မှာ `return navigate('/login');` redirection ကို `return logout();` နဲ့အစားထိုးပါ။ -အကောင့်အသစ်တစ်ခု register လုပ်ပြီး၊ logout နှင့် login ပြန်လုပ်ပါ။ အားလုံး အဆင်ပြေသလား စစ်ဆေးပါ။ +Account အသစ်တစ်ခု register လုပ်ပြီး၊ logout လုပ်ပြီးပြန် login လုပ်ကြည့်ပါ၊ အားလုံးအဆင်ပြေစွာလုပ်ဆောင်နေတယ်ဆိုတာစစ်ဆေးပါ။ -> အကြံပြုချက်- `updateState()` ၏ အောက်ဆုံးတွင် `console.log(state)` ကို ထည့်ပြီး၊ browser development tools တွင် console ကို ဖွင့်ကာ state ပြောင်းလဲမှုအားလုံးကို ကြည့်ရှုနိုင်သည်။ +> အကြံပြုချက်- state ပြောင်းလဲမှုအားလုံးကို browser ရဲ့ development tools မှာ console ကိုဖွင့်ပြီး `updateState()` ရဲ့အောက်ဆုံးမှာ `console.log(state)` ထည့်ပြီးကြည့်နိုင်ပါတယ်။ -## state ကို ထိန်းသိမ်းခြင်း +## State ကိုတည်ရှိနေစေခြင်း -ဝက်ဘ်အက်ပ်များအများစုသည် data ကို ထိန်းသိမ်းရန် လိုအပ်သည်။ အရေးကြီးသော data အားလုံးကို database တွင် သိမ်းဆည်းပြီး၊ server API မှတဆင့် access လုပ်သည်။ သို့သော်၊ browser တွင် client app တွင် data တစ်ချို့ကို သိမ်းဆည်းခြင်းသည် အသုံးပြုသူအတွေ့အကြုံကို ပိုမိုကောင်းမွန်စေခြင်း သို့မဟုတ် loading performance ကို တိုးတက်စေခြင်းအတွက် စိတ်ဝင်စားစရာကောင်းသည်။ +ဝက်ဘ်အက်ပ်များအများစုမှာ data ကိုတည်ရှိနေစေရန်လိုအပ်ပါတယ်။ အရေးကြီးသော data အားလုံးကို database မှာသိမ်းဆည်းပြီး server API မှတဆင့် access လုပ်ပါတယ်၊ ဥပမာအားဖြင့် အသုံးပြုသူ account data ကဲ့သို့။ သို့သော်လည်း၊ browser မှာ run လုပ်နေတဲ့ client app မှာ data တစ်ချို့ကိုတည်ရှိနေစေရန်လည်း sometimes အကျိုးရှိပါတယ်၊ user experience ကိုပိုမိုကောင်းမွန်စေဖို့ ဒါမှမဟုတ် loading performance ကိုတိုးတက်စေဖို့။ -browser တွင် data ကို သိမ်းဆည်းလိုပါက၊ အရေးကြီးသော မေးခွန်းများကို မေးရမည်- +Browser မှာ data ကိုတည်ရှိနေစေချင်တဲ့အခါ၊ အရေးကြီးသောမေးခွန်းတစ်ချို့ကိုမေးဖို့လိုအပ်ပါတယ်- -- *ဒီ data သည် sensitive ဖြစ်ပါသလား?* အသုံးပြုသူ၏ password ကဲ့သို့သော sensitive data များကို client တွင် သိမ်းဆည်းရန် ရှောင်ရှားသင့်သည်။ -- *ဒီ data ကို ဘယ်လောက်ကြာအောင် သိမ်းဆည်းလိုပါသလဲ?* ဒီ data ကို လက်ရှိ session အတွက်သာ အသုံးပြုလိုပါသလား၊ ဒါမှမဟုတ် အမြဲတမ်း သိမ်းဆည်းလိုပါသလား? +- *Data က sensitive ဖြစ်ပါသလား?* အသုံးပြုသူရဲ့ password ကဲ့သို့ sensitive data ကို client မှာသိမ်းဆည်းတာကိုရှောင်ရှားသင့်ပါတယ်။ +- *ဒီ data ကိုဘယ်လောက်ကြာကြာထားချင်ပါသလဲ?* ဒီ data ကိုလက်ရှိ session အတွက်သာ access လုပ်ချင်ပါသလား၊ ဒါမှမဟုတ် အမြဲတမ်းသိမ်းဆည်းထားချင်ပါသလား? -ဝက်ဘ်အက်ပ်တွင် data ကို သိမ်းဆည်းရန် နည်းလမ်းများစွာ ရှိသည်။ ဥပမာအားဖြင့်၊ search query ကို URL တွင် သိမ်းဆည်းပြီး၊ အသုံးပြုသူများအကြား မျှဝေနိုင်သည်။ [authentication](https://en.wikipedia.org/wiki/Authentication) အချက်အလက်ကဲ့သို့ server နှင့် data ကို မျှဝေလိုပါက [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ကို အသုံးပြုနိုင်သည်။ +Web app အတွင်းမှာ data ကိုသိမ်းဆည်းဖို့နည်းလမ်းများစွာရှိပါတယ်၊ မိမိရဲ့ရည်ရွယ်ချက်အပေါ်မူတည်ပြီး။ ဥပမာအားဖြင့်၊ search query ကို URL တွေမှာသိမ်းဆည်းပြီး အသုံးပြုသူများအကြားမျှဝေနိုင်ပါတယ်။ [Authentication](https://en.wikipedia.org/wiki/Authentication) အချက်အလက်ကဲ့သို့ server နဲ့မျှဝေဖို့လိုအပ်တဲ့ data အတွက် [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ကိုအသုံးပြုနိုင်ပါတယ်။ -browser API များစွာ ရှိပြီး၊ data သိမ်းဆည်းရန် အထူးစိတ်ဝင်စားစရာကောင်းသော API နှစ်ခု ရှိသည်- +Browser API များစွာရှိပြီး data ကိုသိမ်းဆည်းဖို့အတွက်အခြားရွေးချယ်မှုများလည်းရှိပါတယ်။ အထူးသဖြင့်အကျိုးရှိတဲ့ API နှစ်ခုရှိပါတယ်- -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) တစ်ခုဖြစ်ပြီး၊ လက်ရှိ website-specific data ကို session များအကြား ထိန်းသိမ်းထားနိုင်သည်။ သိမ်းဆည်းထားသော data သည် expiration မရှိပါ။ -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ဒီ API သည် `localStorage` နှင့် တူသော်လည်း၊ session ပြီးဆုံးသည့်အခါ (browser ကို ပိတ်သည့်အခါ) data ကို ဖျက်သိမ်းသည်။ +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) တစ်ခုဖြစ်ပြီး လက်ရှိ website အတွက် data ကို session များအကြားတည်ရှိနေစေပါတယ်။ ဒီ data က expiration မရှိပါဘူး။ +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ဒီ API က `localStorage` နဲ့တူပေမယ့် session ပြီးဆုံးတဲ့အခါ (browser ကိုပိတ်တဲ့အခါ) data ကိုရှင်းလင်းပေးပါတယ်။ -API နှစ်ခုလုံးသည် [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) ကိုသာ သိမ်းဆည်းနိုင်သည်။ complex object များကို သိမ်းဆည်းလိုပါက၊ [`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) format သို့ serialize လုပ်ရန် လိုအပ်သည်။ +API နှစ်ခုလုံးက [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) ကိုသာသိမ်းဆည်းနိုင်ပါတယ်။ Complex object တွေကိုသိမ်းဆည်းချင်ရင် [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) format ကိုအသုံးပြုပြီး serialize လုပ်ဖို့လိုအပ်ပါတယ်၊ [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) ကိုအသုံးပြုပါ။ -✅ server မရှိသော ဝက်ဘ်အက်ပ်တစ်ခု ဖန်တီးလိုပါက၊ [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) ကို အသုံးပြု၍ client တွင် database တစ်ခု ဖန်တီးနိုင်သည်။ ဒီ API သည် အဆင့်မြင့်အသုံးပြုမှုများ သို့မဟုတ် data အများကြီး သိမ်းဆည်းလိုပါက သင့်တော်သည်၊ အကြောင်းမှာ အသုံးပြုရန် ပိုမိုရှုပ်ထွေးသောကြောင့် ဖြစ်သည်။ +✅ Server မရှိတဲ့ web app တစ်ခုကိုဖန်တီးချင်ရင်၊ [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) ကိုအသုံးပြုပြီး client မှာ database တစ်ခုဖန်တီးနိုင်ပါတယ်။ ဒါက advanced use case တွေအတွက်သို့မဟုတ် data အများကြီးသိမ်းဆည်းဖို့လိုအပ်တဲ့အခါအတွက်သာအသုံးပြုသင့်ပါတယ်၊ အလွန်ရှုပ်ထွေးတဲ့အတွက်။ -### လုပ်ငန်း +### Task -အသုံးပြုသူများသည် *Logout* button ကို explicitly နှိပ်သည်အထိ login လုပ်ထားနိုင်ရန် `localStorage` ကို အသုံးပြု၍ account data ကို သိမ်းဆည်းမည်။ အရင်ဆုံး၊ data သိမ်းဆည်းရန် အသုံးပြုမည့် key ကို သတ်မှတ်ပါ။ +အသုံးပြုသူတွေ *Logout* button ကို explicitly click လုပ်တဲ့အချိန်အထိ login လုပ်နေစေချင်ပါတယ်၊ ဒါကြောင့် `localStorage` ကိုအသုံးပြုပြီး account data ကိုသိမ်းဆည်းပါမယ်။ အရင်ဆုံး၊ data ကိုသိမ်းဆည်းဖို့အသုံးပြုမယ့် key ကိုသတ်မှတ်ပါ။ ```js const storageKey = 'savedAccount'; ``` -ထို့နောက် `updateState()` function ၏ အဆုံးတွင် အောက်ပါလိုင်းကို ထည့်ပါ- +ထို့နောက် `updateState()` function ရဲ့အဆုံးမှာဒီလိုလိုင်းတစ်ခုထည့်ပါ- ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -ဒီနည်းလမ်းဖြင့်၊ အသုံးပြုသူ၏ account data ကို သိမ်းဆည်းပြီး၊ state update များအားလုံးကို centralized လုပ်ထားသည့်အတွက် အမြဲတမ်း up-to-date ဖြစ်နေမည်။ ဒီနေရာတွင် ယခင် refactor များ၏ အကျိုးကျေးဇူးကို စတင်ခံစားရမည် 🙂။ +ဒီနည်းလမ်းနဲ့ user account data ကတည်ရှိနေပြီး၊ state update အားလုံးကို centralized လုပ်ထားတဲ့အကျိုးကျေးဇူးကိုရရှိပါတယ်။ ဒီမှာတော့ အရင်ကလုပ်ထားတဲ့ refactor တွေကအကျိုးကျေးဇူးပေးလာ +[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/48) + +## အလုပ်ပေးစာ -data ကို သိမ်းဆည်းထားသည့်အတွက်၊ app ကို load လုပ်သောအခါ data ကို ပြ -[လုပ်ဆောင်ရန် "ငွေသွင်းမှု ထည့်သွင်းရန်" ဆွေးနွေးမှုကို အကောင်အထည်ဖော်ပါ](assignment.md) +[အလုပ်ပေးစာ "Add transaction" dialog ကို အကောင်အထည်ဖော်ပါ](assignment.md) -ဤလုပ်ငန်းကို ပြီးမြောက်ပြီးနောက်ရရှိသော နမူနာရလဒ်ဖြစ်သည် - +အလုပ်ပေးစာကို ပြီးမြောက်ပြီးနောက်ရရှိမည့် ရလဒ်ဥပမာမှာ အောက်ပါအတိုင်းဖြစ်ပါသည် - -!["ငွေသွင်းမှု ထည့်သွင်းရန်" ဆွေးနွေးမှု၏ နမူနာ Screenshot](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.my.png) +![Screenshot showing an example "Add transaction" dialog](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.my.png) --- -**ဝက်ဘ်ဆိုက်မှတ်ချက်**: -ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှန်ကန်မှုအတွက် ကြိုးစားနေသော်လည်း၊ အလိုအလျောက်ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်ကြောင်း သတိပြုပါ။ မူလဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတည်သော ရင်းမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များကို အသုံးပြုရန် အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော နားလည်မှုမှားများ သို့မဟုတ် အဓိပ္ပာယ်မှားများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မရှိပါ။ \ No newline at end of file +**အကြောင်းကြားချက်**: +ဤစာရွက်စာတမ်းကို AI ဘာသာပြန်ဝန်ဆောင်မှု [Co-op Translator](https://github.com/Azure/co-op-translator) ကို အသုံးပြု၍ ဘာသာပြန်ထားပါသည်။ ကျွန်ုပ်တို့သည် တိကျမှုအတွက် ကြိုးစားနေသော်လည်း အလိုအလျောက် ဘာသာပြန်ခြင်းတွင် အမှားများ သို့မဟုတ် မမှန်ကန်မှုများ ပါဝင်နိုင်သည်ကို သတိပြုပါ။ မူရင်းဘာသာစကားဖြင့် ရေးသားထားသော စာရွက်စာတမ်းကို အာဏာတရ အရင်းအမြစ်အဖြစ် သတ်မှတ်သင့်ပါသည်။ အရေးကြီးသော အချက်အလက်များအတွက် လူ့ဘာသာပြန်ပညာရှင်များမှ ဘာသာပြန်ခြင်းကို အကြံပြုပါသည်။ ဤဘာသာပြန်ကို အသုံးပြုခြင်းမှ ဖြစ်ပေါ်လာသော အလွဲအလွတ်များ သို့မဟုတ် အနားယူမှုမှားများအတွက် ကျွန်ုပ်တို့သည် တာဝန်မယူပါ။ \ No newline at end of file diff --git a/translations/ne/7-bank-project/4-state-management/README.md b/translations/ne/7-bank-project/4-state-management/README.md index 84c0b79b8..fb07179f9 100644 --- a/translations/ne/7-bank-project/4-state-management/README.md +++ b/translations/ne/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# बैंकिङ एप निर्माण भाग ४: स्टेट म्यानेजमेन्टको अवधारणा +# बैंकिङ एप बनाउनुहोस् भाग ४: स्टेट म्यानेजमेन्टका अवधारणाहरू ## प्रि-लेक्चर क्विज @@ -15,15 +15,15 @@ CO_OP_TRANSLATOR_METADATA: ### परिचय -जसरी वेब एप्लिकेसन बढ्दै जान्छ, सबै डेटा प्रवाहलाई ट्र्याक गर्नु चुनौतीपूर्ण हुन्छ। कुन कोडले डेटा प्राप्त गर्छ, कुन पेजले यसलाई प्रयोग गर्छ, कहिले र कहाँ यसलाई अपडेट गर्नुपर्छ... यो सजिलै जटिल कोडमा परिणत हुन सक्छ जसलाई मर्मत गर्न गाह्रो हुन्छ। यो विशेष गरी सत्य हो जब तपाईंले आफ्नो एपका विभिन्न पेजहरूमा डेटा साझा गर्न आवश्यक हुन्छ, जस्तै प्रयोगकर्ता डेटा। *स्टेट म्यानेजमेन्ट* को अवधारणा सबै प्रकारका प्रोग्रामहरूमा सधैं रहेको छ, तर वेब एपहरू जटिलतामा बढ्दै जाँदा यो विकासको क्रममा सोच्नुपर्ने मुख्य बिन्दु बनेको छ। +जसरी वेब एप्लिकेसन ठूलो हुँदै जान्छ, सबै डेटा प्रवाहहरू ट्र्याक गर्न गाह्रो हुन्छ। कुन कोडले डेटा लिन्छ, कुन पृष्ठले यसलाई प्रयोग गर्छ, कहिले र कहाँ अपडेट गर्नुपर्छ... सजिलैसँग जटिल कोड बन्न सक्छ जसलाई मर्मत गर्न गाह्रो हुन्छ। यो विशेष गरी सत्य हो जब तपाईंले आफ्नो एपका विभिन्न पृष्ठहरूमा डेटा साझा गर्नुपर्छ, जस्तै प्रयोगकर्ता डेटा। *स्टेट म्यानेजमेन्ट* को अवधारणा सबै प्रकारका प्रोग्रामहरूमा सधैं अस्तित्वमा रहेको छ, तर वेब एपहरू जटिल हुँदै जाँदा यो विकासको क्रममा सोच्नुपर्ने मुख्य बिन्दु बनेको छ। -यस अन्तिम भागमा, हामीले बनाएको एपलाई पुनः हेर्नेछौं ताकि स्टेटलाई व्यवस्थापन गर्न सकियोस्, ब्राउजर रिफ्रेसलाई कुनै पनि समयमा समर्थन गर्न सकियोस्, र प्रयोगकर्ता सत्रहरूमा डेटा कायम राख्न सकियोस्। +यस अन्तिम भागमा, हामीले बनाएको एपलाई पुनः हेर्नेछौं र स्टेट कसरी व्यवस्थापन गरिन्छ भन्ने कुरा पुनर्विचार गर्नेछौं, जसले ब्राउजर रिफ्रेसलाई कुनै पनि समयमा समर्थन गर्न र प्रयोगकर्ता सत्रहरूमा डेटा कायम राख्न अनुमति दिन्छ। -### पूर्वापेक्षा +### पूर्वआवश्यकता -यस पाठको लागि तपाईंले वेब एपको [डेटा फेचिङ](../3-data/README.md) भाग पूरा गरिसक्नुपर्छ। तपाईंले [Node.js](https://nodejs.org) स्थापना गर्नुपर्छ र [सर्भर API](../api/README.md) स्थानीय रूपमा चलाउनुपर्छ ताकि तपाईं खाता डेटा व्यवस्थापन गर्न सक्नुहुन्छ। +यस पाठको लागि तपाईंले वेब एपको [डेटा फेचिङ](../3-data/README.md) भाग पूरा गरिसक्नुपर्छ। तपाईंले [Node.js](https://nodejs.org) स्थापना गर्नुपर्छ र [सर्भर एपीआई](../api/README.md) लाई स्थानीय रूपमा चलाउनुपर्छ ताकि तपाईं खाता डेटा व्यवस्थापन गर्न सक्नुहुन्छ। -तपाईंले सर्भर ठीकसँग चलिरहेको छ कि छैन भनेर जाँच गर्न टर्मिनलमा यो कमाण्ड चलाउन सक्नुहुन्छ: +तपाईंले यो कमाण्ड टर्मिनलमा चलाएर सर्भर ठीकसँग चलिरहेको छ कि छैन परीक्षण गर्न सक्नुहुन्छ: ```sh curl http://localhost:5000/api @@ -32,36 +32,36 @@ curl http://localhost:5000/api --- -## स्टेट म्यानेजमेन्ट पुनः विचार गर्नुहोस् +## स्टेट म्यानेजमेन्ट पुनर्विचार गर्नुहोस् -[अघिल्लो पाठ](../3-data/README.md) मा, हामीले हाम्रो एपमा ग्लोबल `account` भेरिएबलको साथ स्टेटको आधारभूत अवधारणा प्रस्तुत गरेका थियौं, जसले हालको लगइन गरिएको प्रयोगकर्ताको बैंक डेटा समावेश गर्दछ। तर, हाम्रो हालको कार्यान्वयनमा केही कमजोरीहरू छन्। ड्यासबोर्डमा हुँदा पेज रिफ्रेस गर्नुहोस्। के हुन्छ? +[अघिल्लो पाठ](../3-data/README.md) मा, हामीले हाम्रो एपमा स्टेटको आधारभूत अवधारणा प्रस्तुत गर्यौं, जसमा `account` नामक ग्लोबल भेरिएबलले हाल लगइन गरिएको प्रयोगकर्ताको बैंक डेटा समावेश गर्दछ। तर, हाम्रो हालको कार्यान्वयनमा केही कमजोरीहरू छन्। ड्यासबोर्डमा हुँदा पृष्ठ रिफ्रेस गरेर प्रयास गर्नुहोस्। के हुन्छ? हालको कोडमा ३ समस्या छन्: -- स्टेट कायम रहँदैन, किनकि ब्राउजर रिफ्रेसले तपाईंलाई लगइन पेजमा फर्काउँछ। -- स्टेटलाई परिवर्तन गर्ने धेरै फङ्सनहरू छन्। एप बढ्दै जाँदा, यसले परिवर्तनहरू ट्र्याक गर्न गाह्रो बनाउँछ र एउटा अपडेट गर्न बिर्सन सजिलो हुन्छ। -- स्टेट सफा गरिँदैन, त्यसैले जब तपाईं *Logout* क्लिक गर्नुहुन्छ, खाता डेटा अझै त्यहाँ हुन्छ, यद्यपि तपाईं लगइन पेजमा हुनुहुन्छ। +- स्टेट कायम हुँदैन, किनभने ब्राउजर रिफ्रेस गर्दा तपाईंलाई लगइन पृष्ठमा फिर्ता लैजान्छ। +- स्टेट परिवर्तन गर्ने धेरै फङ्सनहरू छन्। एप ठूलो हुँदै जाँदा, यसले परिवर्तनहरू ट्र्याक गर्न गाह्रो बनाउँछ र कुनै एक अपडेट गर्न बिर्सन सजिलो हुन्छ। +- स्टेट सफा गरिँदैन, त्यसैले जब तपाईं *Logout* क्लिक गर्नुहुन्छ, खाता डेटा अझै त्यहाँ हुन्छ, यद्यपि तपाईं लगइन पृष्ठमा हुनुहुन्छ। -हामी यी समस्याहरूलाई एक-एक गरेर समाधान गर्न कोड अपडेट गर्न सक्थ्यौं, तर यसले कोड दोहोर्याउने र एपलाई अझ जटिल र मर्मत गर्न गाह्रो बनाउँछ। वा हामी केही मिनेट रोक्न सक्थ्यौं र हाम्रो रणनीति पुनः विचार गर्न सक्थ्यौं। +हामी यी समस्याहरूलाई एक-एक गरी समाधान गर्न कोड अपडेट गर्न सक्छौं, तर यसले कोड दोहोर्याउने र एपलाई अझ जटिल र मर्मत गर्न गाह्रो बनाउनेछ। वा हामी केही मिनेट रोक्न सक्छौं र हाम्रो रणनीतिलाई पुनर्विचार गर्न सक्छौं। > यहाँ हामी वास्तवमा कुन समस्याहरू समाधान गर्न खोजिरहेका छौं? -[स्टेट म्यानेजमेन्ट](https://en.wikipedia.org/wiki/State_management) भनेको यी दुई विशेष समस्याहरू समाधान गर्न राम्रो दृष्टिकोण खोज्नु हो: +[स्टेट म्यानेजमेन्ट](https://en.wikipedia.org/wiki/State_management) भनेको यी दुई विशेष समस्याहरू समाधान गर्न राम्रो दृष्टिकोण फेला पार्नु हो: - एपमा डेटा प्रवाहलाई कसरी बुझ्न सकिने बनाउने? -- स्टेट डेटा सधैं प्रयोगकर्ता इन्टरफेससँग (र उल्टो) कसरी समन्वयमा राख्ने? +- स्टेट डेटा सधैं प्रयोगकर्ता इन्टरफेससँग (र यसको उल्टो) कसरी समन्वयमा राख्ने? -यी समस्याहरू समाधान गरेपछि, तपाईंले सामना गर्न सक्ने अन्य समस्याहरू या त पहिले नै समाधान भएका हुन सक्छन् वा समाधान गर्न सजिलो भएका हुन सक्छन्। यी समस्याहरू समाधान गर्न धेरै सम्भावित दृष्टिकोणहरू छन्, तर हामी **डेटा र यसलाई परिवर्तन गर्ने तरिकाहरूलाई केन्द्रित गर्ने** सामान्य समाधानमा जानेछौं। डेटा प्रवाह यसरी जानेछ: +यी समस्याहरू समाधान गरेपछि, तपाईंले सामना गर्न सक्ने अन्य कुनै पनि समस्याहरू पहिले नै समाधान भइसकेका हुन सक्छन् वा समाधान गर्न सजिलो भएका हुन सक्छन्। यी समस्याहरू समाधान गर्न धेरै सम्भावित दृष्टिकोणहरू छन्, तर हामी **डेटा र यसलाई परिवर्तन गर्ने तरिकाहरूलाई केन्द्रीकृत गर्ने** सामान्य समाधान अपनाउनेछौं। डेटा प्रवाह यसरी जानेछ: -![HTML, प्रयोगकर्ता क्रियाकलाप र स्टेट बीचको डेटा प्रवाह देखाउने स्कीमा](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.ne.png) +![HTML, प्रयोगकर्ता क्रियाकलाप र स्टेट बीचको डेटा प्रवाह देखाउने स्किमा](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.ne.png) -> यहाँ हामी डेटा स्वतः दृश्य अपडेट ट्रिगर गर्ने भाग कभर गर्ने छैनौं, किनकि यो [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) को अधिक उन्नत अवधारणासँग सम्बन्धित छ। यदि तपाईं गहिरो अध्ययन गर्न इच्छुक हुनुहुन्छ भने यो राम्रो विषय हो। +> यहाँ हामी डेटा स्वचालित रूपमा भ्यू अपडेट ट्रिगर गर्ने भाग कभर गर्नेछैनौं, किनभने यो [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming) का थप उन्नत अवधारणाहरूमा आधारित छ। यदि तपाईं गहिरो अध्ययन गर्न इच्छुक हुनुहुन्छ भने यो राम्रो विषय हो। -✅ स्टेट म्यानेजमेन्टका लागि विभिन्न दृष्टिकोणहरू भएका धेरै लाइब्रेरीहरू छन्, [Redux](https://redux.js.org) एक लोकप्रिय विकल्प हो। यसमा प्रयोग गरिएका अवधारणाहरू र ढाँचाहरू हेर्नुहोस्, किनकि यो प्रायः ठूलो वेब एपहरूमा तपाईंले सामना गर्न सक्ने सम्भावित समस्याहरू र तिनीहरूलाई कसरी समाधान गर्न सकिन्छ भन्ने सिक्ने राम्रो तरिका हो। +✅ स्टेट म्यानेजमेन्टका लागि विभिन्न दृष्टिकोणहरू भएका धेरै पुस्तकालयहरू छन्, [Redux](https://redux.js.org) एक लोकप्रिय विकल्प हो। यसमा प्रयोग गरिएका अवधारणाहरू र ढाँचाहरू हेर्नुहोस्, किनभने यो ठूलो वेब एपहरूमा तपाईंले सामना गर्न सक्ने सम्भावित समस्याहरू र तिनीहरूलाई कसरी समाधान गर्न सकिन्छ भन्ने कुरा सिक्नको लागि प्रायः राम्रो तरिका हो। ### कार्य -हामी थोरै रिफ्याक्टरिङबाट सुरु गर्नेछौं। `account` घोषणा प्रतिस्थापन गर्नुहोस्: +हामी थोरै कोड पुनर्संरचना गरेर सुरु गर्नेछौं। `account` घोषणा प्रतिस्थापन गर्नुहोस्: ```js let account = null; @@ -75,25 +75,25 @@ let state = { }; ``` -विचार भनेको हाम्रो एप डेटा सबैलाई एकल स्टेट वस्तुमा *केन्द्रित* गर्नु हो। अहिले स्टेटमा हामीसँग `account` मात्र छ, त्यसैले यसले धेरै परिवर्तन गर्दैन, तर यसले विकासको लागि मार्ग बनाउँछ। +यो विचार हाम्रो सम्पूर्ण एप डेटा एकल स्टेट वस्तुमा *केन्द्रीकृत* गर्ने हो। अहिले स्टेटमा केवल `account` छ, त्यसैले यसले धेरै परिवर्तन गर्दैन, तर यसले भविष्यका विकासहरूको लागि बाटो खोल्छ। -हामी यसलाई प्रयोग गर्ने फङ्सनहरू पनि अपडेट गर्नुपर्छ। `register()` र `login()` फङ्सनहरूमा, `account = ...` लाई `state.account = ...` ले प्रतिस्थापन गर्नुहोस्; +हामीले यसलाई प्रयोग गर्ने फङ्सनहरू पनि अपडेट गर्नुपर्छ। `register()` र `login()` फङ्सनहरूमा, `account = ...` लाई `state.account = ...` ले प्रतिस्थापन गर्नुहोस्; -`updateDashboard()` फङ्सनको शीर्षमा, यो लाइन थप्नुहोस्: +`updateDashboard()` फङ्सनको सुरुमा, यो लाइन थप्नुहोस्: ```js const account = state.account; ``` -यो रिफ्याक्टरिङले आफैंमा धेरै सुधार ल्याएको छैन, तर विचार भनेको आगामी परिवर्तनहरूको लागि आधार तयार गर्नु हो। +यो पुनर्संरचनाले आफैंमा धेरै सुधार ल्याएन, तर विचार आगामी परिवर्तनहरूको लागि आधार तयार गर्नु थियो। -## डेटा परिवर्तन ट्र्याक गर्नुहोस् +## डेटा परिवर्तनहरू ट्र्याक गर्नुहोस् -अब हामीले हाम्रो डेटा भण्डारण गर्न `state` वस्तु राखेका छौं, अर्को चरण भनेको अपडेटहरू केन्द्रित गर्नु हो। उद्देश्य भनेको कुनै पनि परिवर्तनहरू र तिनीहरू कहिले हुन्छन् भनेर ट्र्याक गर्न सजिलो बनाउनु हो। +अब हामीले डेटा भण्डारण गर्न `state` वस्तु राखेका छौं, अर्को चरण भनेको अपडेटहरू केन्द्रीकृत गर्नु हो। उद्देश्य भनेको कुनै पनि परिवर्तनहरू र तिनीहरू कहिले हुन्छन् भन्ने कुरा ट्र्याक गर्न सजिलो बनाउनु हो। -`state` वस्तुमा परिवर्तनहरू गर्नबाट बच्न, यसलाई [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) मान्नु राम्रो अभ्यास हो, जसको अर्थ यसलाई बिल्कुलै परिवर्तन गर्न सकिँदैन। यसको मतलब तपाईंले यसमा केही परिवर्तन गर्न चाहनुहुन्छ भने नयाँ स्टेट वस्तु सिर्जना गर्नुपर्छ। यसो गर्दा, तपाईंले सम्भावित अवांछित [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) को बारेमा सुरक्षा निर्माण गर्नुहुन्छ, र तपाईंको एपमा नयाँ सुविधाहरू कार्यान्वयन गर्ने सम्भावनाहरू खोल्नुहुन्छ जस्तै undo/redo लागू गर्ने, साथै डिबग गर्न सजिलो बनाउने। उदाहरणका लागि, तपाईंले स्टेटमा गरिएका प्रत्येक परिवर्तनलाई लग गर्न सक्नुहुन्छ र बगको स्रोत बुझ्न परिवर्तनहरूको इतिहास राख्न सक्नुहुन्छ। +`state` वस्तुमा परिवर्तनहरू हुन नदिन, यसलाई [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) मान्नु राम्रो अभ्यास हो, जसको अर्थ यसलाई कुनै पनि रूपमा परिवर्तन गर्न सकिँदैन। यसको मतलब तपाईंले यसमा केही परिवर्तन गर्न चाहनुहुन्छ भने नयाँ स्टेट वस्तु सिर्जना गर्नुपर्छ। यसो गर्दा, तपाईंले सम्भावित अवाञ्छित [साइड इफेक्ट्स](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) बाट सुरक्षा निर्माण गर्नुहुन्छ, र तपाईंको एपमा नयाँ सुविधाहरू कार्यान्वयन गर्ने सम्भावनाहरू खोल्नुहुन्छ, जस्तै undo/redo कार्यान्वयन गर्नु, साथै डिबग गर्न सजिलो बनाउनु। उदाहरणका लागि, तपाईंले स्टेटमा गरिएका प्रत्येक परिवर्तनलाई लग गर्न सक्नुहुन्छ र बगको स्रोत बुझ्न परिवर्तनहरूको इतिहास राख्न सक्नुहुन्छ। -जाभास्क्रिप्टमा, [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) प्रयोग गरेर वस्तुको अपरिवर्तनीय संस्करण सिर्जना गर्न सकिन्छ। यदि तपाईंले अपरिवर्तनीय वस्तुमा परिवर्तन गर्न प्रयास गर्नुभयो भने, अपवाद उठाइनेछ। +जाभास्क्रिप्टमा, [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) प्रयोग गरेर वस्तुको अपरिवर्तनीय संस्करण सिर्जना गर्न सकिन्छ। यदि तपाईंले अपरिवर्तनीय वस्तुमा परिवर्तन गर्न प्रयास गर्नुभयो भने, अपवाद उत्पन्न हुनेछ। ✅ के तपाईंलाई *shallow* र *deep* अपरिवर्तनीय वस्तु बीचको भिन्नता थाहा छ? तपाईं यसबारे [यहाँ](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) पढ्न सक्नुहुन्छ। @@ -110,9 +110,9 @@ function updateState(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` सम्पत्ति मात्र छ, तर यस दृष्टिकोणले तपाईंलाई स्टेटमा आवश्यक जति सम्पत्तिहरू थप्न अनुमति दिन्छ। +यस फङ्सनमा, हामी नयाँ स्टेट वस्तु सिर्जना गर्दैछौं र [*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({ @@ -120,13 +120,13 @@ let state = Object.freeze({ }); ``` -त्यसपछि, `register` फङ्सनलाई अपडेट गर्नुहोस् र `state.account = result;` असाइनमेन्टलाई प्रतिस्थापन गर्नुहोस्: +त्यसपछि, `register` फङ्सनलाई `state.account = result;` असाइनमेन्टलाई प्रतिस्थापन गरेर अपडेट गर्नुहोस्: ```js updateState('account', result); ``` -`login` फङ्सनसँग पनि त्यस्तै गर्नुहोस्, `state.account = data;` लाई प्रतिस्थापन गर्नुहोस्: +`login` फङ्सनमा पनि त्यस्तै गर्नुहोस्, `state.account = data;` लाई प्रतिस्थापन गरेर: ```js updateState('account', data); @@ -143,35 +143,35 @@ function logout() { } ``` -`updateDashboard()` मा, `return navigate('/login');` रिडिरेक्शनलाई `return logout();` ले प्रतिस्थापन गर्नुहोस्; +`updateDashboard()` मा, `return navigate('/login');` पुनर्निर्देशनलाई `return logout();` ले प्रतिस्थापन गर्नुहोस्; -नयाँ खाता दर्ता गर्ने, लग आउट गर्ने र फेरि लग इन गर्ने प्रयास गर्नुहोस् ताकि सबै कुरा अझै ठीकसँग काम गरिरहेको छ कि छैन जाँच गर्नुहोस्। +नयाँ खाता दर्ता गर्ने, लगआउट गर्ने र फेरि लगइन गर्ने प्रयास गर्नुहोस् ताकि सबै कुरा अझै ठीकसँग काम गरिरहेको छ कि छैन जाँच गर्नुहोस्। -> टिप: तपाईंले `updateState()` को तल `console.log(state)` थपेर र आफ्नो ब्राउजरको विकास उपकरणमा कन्सोल खोलेर सबै स्टेट परिवर्तनहरू हेर्न सक्नुहुन्छ। +> सुझाव: तपाईंले `updateState()` को तल `console.log(state)` थपेर र आफ्नो ब्राउजरको विकास उपकरणहरूमा कन्सोल खोलेर सबै स्टेट परिवर्तनहरू हेर्न सक्नुहुन्छ। ## स्टेट कायम राख्नुहोस् -धेरै वेब एपहरू सही रूपमा काम गर्न डेटा कायम राख्न आवश्यक हुन्छ। सबै महत्त्वपूर्ण डेटा सामान्यतया डेटाबेसमा भण्डारण गरिन्छ र सर्भर API मार्फत पहुँच गरिन्छ, जस्तै हाम्रो केसमा प्रयोगकर्ता खाता डेटा। तर कहिलेकाहीँ, ब्राउजरमा चलिरहेको क्लाइन्ट एपमा केही डेटा कायम राख्नु पनि रोचक हुन्छ, राम्रो प्रयोगकर्ता अनुभवको लागि वा लोडिङ प्रदर्शन सुधार गर्न। +धेरैजसो वेब एपहरू सही रूपमा काम गर्न डेटा कायम राख्न आवश्यक हुन्छ। सबै महत्त्वपूर्ण डेटा सामान्यतया डेटाबेसमा भण्डारण गरिन्छ र सर्भर एपीआई मार्फत पहुँच गरिन्छ, जस्तै हाम्रो केसमा प्रयोगकर्ता खाता डेटा। तर कहिलेकाहीँ, ब्राउजरमा चलिरहेको क्लाइन्ट एपमा केही डेटा कायम राख्नु पनि उपयोगी हुन्छ, राम्रो प्रयोगकर्ता अनुभवको लागि वा लोडिङ प्रदर्शन सुधार गर्न। -जब तपाईं आफ्नो ब्राउजरमा डेटा कायम राख्न चाहनुहुन्छ, केही महत्त्वपूर्ण प्रश्नहरू सोध्नुपर्छ: +जब तपाईं आफ्नो ब्राउजरमा डेटा कायम राख्न चाहनुहुन्छ, तपाईंले केही महत्त्वपूर्ण प्रश्नहरू सोध्नुपर्छ: -- *डेटा संवेदनशील छ?* तपाईंले क्लाइन्टमा कुनै पनि संवेदनशील डेटा भण्डारण गर्नबाट बच्नुपर्छ, जस्तै प्रयोगकर्ता पासवर्डहरू। -- *तपाईंलाई यो डेटा कति समयसम्म राख्न आवश्यक छ?* तपाईंले यो डेटा केवल वर्तमान सत्रको लागि पहुँच गर्न चाहनुहुन्छ वा यसलाई सधैंको लागि भण्डारण गर्न चाहनुहुन्छ? +- *डेटा संवेदनशील छ?* तपाईंले क्लाइन्टमा कुनै पनि संवेदनशील डेटा, जस्तै प्रयोगकर्ता पासवर्डहरू भण्डारण गर्नबाट बच्नुपर्छ। +- *तपाईंलाई यो डेटा कति समयसम्म राख्न आवश्यक छ?* के तपाईंले यो डेटा केवल हालको सत्रको लागि पहुँच गर्न चाहनुहुन्छ वा तपाईं यसलाई सधैंको लागि भण्डारण गर्न चाहनुहुन्छ? -वेब एप भित्र जानकारी भण्डारण गर्ने धेरै तरिकाहरू छन्, तपाईंले के हासिल गर्न चाहनुहुन्छ भन्नेमा निर्भर गर्दै। उदाहरणका लागि, तपाईंले खोज क्वेरी भण्डारण गर्न URL प्रयोग गर्न सक्नुहुन्छ, र यसलाई प्रयोगकर्ताहरू बीच साझा गर्न सक्नुहुन्छ। तपाईंले [HTTP कुकीहरू](https://developer.mozilla.org/docs/Web/HTTP/Cookies) प्रयोग गर्न सक्नुहुन्छ यदि डेटा सर्भरसँग साझा गर्न आवश्यक छ, जस्तै [प्रमाणीकरण](https://en.wikipedia.org/wiki/Authentication) जानकारी। +वेब एप भित्र जानकारी भण्डारण गर्ने धेरै तरिकाहरू छन्, तपाईंले के हासिल गर्न चाहनुहुन्छ भन्ने कुरामा निर्भर गर्दै। उदाहरणका लागि, तपाईंले URL हरू प्रयोग गरेर खोज क्वेरी भण्डारण गर्न सक्नुहुन्छ, र यसलाई प्रयोगकर्ताहरू बीच साझा गर्न सक्नुहुन्छ। तपाईंले [HTTP कुकीहरू](https://developer.mozilla.org/docs/Web/HTTP/Cookies) पनि प्रयोग गर्न सक्नुहुन्छ यदि डेटा सर्भरसँग साझा गर्न आवश्यक छ भने, जस्तै [प्रमाणीकरण](https://en.wikipedia.org/wiki/Authentication) जानकारी। -अर्को विकल्प भनेको डेटा भण्डारण गर्न ब्राउजर 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` जस्तै काम गर्छ तर यसमा भण्डारण गरिएको डेटा सत्र समाप्त हुँदा (ब्राउजर बन्द हुँदा) सफा गरिन्छ। +- [`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) ढाँचामा सिरियलाइज गर्नुपर्नेछ। +ध्यान दिनुहोस् कि यी दुवै एपीआईहरूले केवल [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) भण्डारण गर्न अनुमति दिन्छ। यदि तपाईंले जटिल वस्तुहरू भण्डारण गर्न चाहनुहुन्छ भने, तपाईंले यसलाई [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) ढाँचामा सिरियलाइज गर्नुपर्नेछ [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) प्रयोग गरेर। -✅ यदि तपाईं सर्भर बिना काम गर्ने वेब एप बनाउन चाहनुहुन्छ भने, [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) प्रयोग गरेर क्लाइन्टमा डेटाबेस सिर्जना गर्न पनि सम्भव छ। यो उन्नत प्रयोगका लागि आरक्षित छ वा यदि तपाईंले महत्वपूर्ण मात्रामा डेटा भण्डारण गर्न आवश्यक छ भने, किनकि यो प्रयोग गर्न अधिक जटिल छ। +✅ यदि तपाईं सर्भर बिना काम गर्ने वेब एप बनाउन चाहनुहुन्छ भने, यो पनि सम्भव छ कि क्लाइन्टमा डेटाबेस सिर्जना गर्न [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) प्रयोग गर्नुहोस्। यो उन्नत प्रयोगका लागि वा यदि तपाईंलाई ठूलो मात्रामा डेटा भण्डारण गर्न आवश्यक छ भने आरक्षित छ, किनभने यो प्रयोग गर्न अधिक जटिल छ। ### कार्य -हामी चाहन्छौं कि हाम्रो प्रयोगकर्ताहरू स्पष्ट रूपमा *Logout* बटन क्लिक नगरेसम्म लगइन रहून्, त्यसैले हामी `localStorage` प्रयोग गरेर खाता डेटा भण्डारण गर्नेछौं। पहिलो, हामीले डेटा भण्डारण गर्न प्रयोग गर्ने कुञ्जी परिभाषित गरौं। +हामी चाहन्छौं कि हाम्रो प्रयोगकर्ताहरू *Logout* बटनमा स्पष्ट रूपमा क्लिक नगरेसम्म लगइन रहून्, त्यसैले हामी `localStorage` प्रयोग गरेर खाता डेटा भण्डारण गर्नेछौं। पहिलो, हामीले हाम्रो डेटा भण्डारण गर्न प्रयोग गर्ने कुञ्जी परिभाषित गरौं। ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -यससँग, प्रयोगकर्ता खाता डेटा कायम रहनेछ र हामीले पहिले केन्द्रित गरेका सबै स्टेट अपडेटहरू जस्तै सधैं अद्यावधिक हुनेछ। यहीँबाट हामीले गरेका सबै रिफ्याक्टरिङको फाइदा लिन सुरु गर्छौं 🙂। +यससँग, प्रयोगकर्ता खाता डेटा कायम हुनेछ र सबै समय अद्यावधिक हुनेछ, किनभने हामीले पहिले नै हाम्रो सबै स्टेट अपडेटहरू केन्द्रीकृत गरेका छौं। यहीँबाट हामीले गरेका सबै पुनर्संरचनाहरूको फाइदा लिन सुरु गर्छौं 🙂। -जसरी डेटा बचत गरिन्छ, हामीले एप लोड हुँदा यसलाई पुनःस्थापित गर्न पनि ध्यान दिनुपर्छ। किनकि हामीले अधिक सुरुवात कोड राख्न थाल्छौं, नयाँ `init` फङ्सन सिर्जना गर्नु राम्रो विचार हुन सक्छ, जसले `app.js` को तलको हाम्रो अघिल्लो कोड पनि समावेश गर्दछ: +डेटा भण्डारण गरिएको छ, त्यसैले एप लोड हुँदा यसलाई पुनःस्थापना गर्न पनि ध्यान दिनुपर्छ। किनभने हामीसँग अब धेरै सुरुवात कोड हुनेछ, नयाँ `init` फङ्सन सिर्जना गर्नु राम्रो विचार हुन सक्छ, जसले `app.js` को तलको हाम्रो अघिल्लो कोड पनि समावेश गर्दछ: ```js function init() { @@ -202,11 +202,11 @@ function init() { init(); ``` -यहाँ हामीले बचत गरिएको डेटा पुनः प्राप्त गर्छौं, र यदि त्यहाँ कुनै छ भने हामी स्टेटलाई त्यस अनुसार अपडेट गर्छौं। यो पेज अपडेटको क्रममा स्टेटमा निर्भर कोड हुन सक्ने भएकाले *रूट अपडेट गर्नु अघि* गर्न महत्त्वपूर्ण छ। +यहाँ हामीले भण्डारण गरिएको डेटा पुनःप्राप्त गर्छौं, र यदि कुनै छ भने हामी स्टेटलाई त्यस अनुसार अद्यावधिक गर्छौं। यो पृष्ठ अद्यावधिकको क्रममा स्टेटमा निर्भर कोड हुन सक्छ, त्यसैले यो *रूट अपडेट गर्नु अघि* गर्न महत्त्वपूर्ण छ। -हामीले *Dashboard* पेजलाई हाम्रो एपको डिफल्ट पेज बनाउन पनि सक्दछौं, किनकि हामी अब खाता डेटा कायम राख्दैछौं। यदि कुनै डेटा फेला परेन भने, ड्यासबोर्डले *Login* पेजमा रिडिरेक्ट गर्ने काम गर्छ। `updateRoute()` मा, फलब्याक `return navigate('/login');` लाई `return navigate('/dashboard');` ले प्रतिस्थापन गर्नुहोस्। +हामी *Dashboard* पृष्ठलाई हाम्रो एपको डिफल्ट पृष्ठ बनाउन सक्छौं, किनभने अब हामी खाता डेटा कायम राख्दैछौं। यदि कुनै डेटा फेला परेन भने, ड्यासबोर्डले *Login* पृष्ठमा पुनर्निर्देशनको ख्याल राख्छ। `updateRoute()` मा, फलब्याक `return navigate('/login');` लाई `return navigate('/dashboard');` ले प्रतिस्थापन गर्नुहोस्। -अब एपमा लगइन गर्नुहोस् र पेज रिफ्रेस गर्ने प्रयास गर्नुहोस्। तपाईं ड्यासबोर्डमा रहनुहुन्छ। यस अपडेटसँगै हामीले हाम्रो प्रारम्भिक समस्याहरूको ख्याल गरेका छौं... +अब एपमा लगइन गर्नुहोस् र पृष्ठ रिफ्रेस गर्ने प्रयास गर्नुहोस्। तपाईं ड्यासबोर्डमा रहनु पर्छ। यस अद्यावधिकसँग, हामीले हाम्रो सबै प्रारम्भिक समस्याहरू समाधान गरेका छौं... ## डेटा रिफ्रेस गर्नुहोस् @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -अब ब्राउजरमा ड्यासबोर्ड पेज रिफ्रेस गर्ने प्रयास गर्नुहोस्। के हुन्छ? के तपाईंले नयाँ ट्रान्जेक्सन देख्नुभयो? +अब आफ्नो ब्राउजरमा ड्यासबोर्ड पृष्ठ रिफ्रेस गर्ने प्रयास गर्नुहोस्। के हुन्छ? के तपाईंले नयाँ ट्रान्जेक्सन देख्नुभयो? -स्टेट `localStorage` को कारण अनिश्चितकालसम्म कायम रहन्छ, तर यसको मतलब यो कहिल्यै अपडेट हुँदैन जबसम्म तपाईं एपबाट लग आउट गरेर फेरि लग इन गर्नुहुन्न! +स्टेट `localStorage` को कारण अनिश्चितकालसम्म कायम रहन्छ, तर यसको मतलब यो कहिल्यै अद्यावधिक हुँदैन जबसम्म तपाईं एपबाट लगआउट गरेर फेरि लगइन गर्नुहुन्न! यसलाई समाधान गर्ने सम्भावित रणनीति भनेको ड्यासबोर्ड लोड हुँदा हरेक पटक खाता डेटा पुनः लोड गर्नु हो, ताकि पुरानो डेटा नहोस्। @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -यो मेथडले जाँच गर्छ कि हामी हाल लगइन गरिरहेका छौं र त्यसपछि सर्भरबाट खाता डेटा पुनः लोड गर्छ। +यस विधिले जाँच गर्छ कि हामी हाल लगइन गरिरहेका छौं र त्यसपछि सर्भरबाट खाता डेटा पुनः लोड गर्छ। `refresh` नामक अर्को फङ्सन सिर्जना गर्नुहोस्: @@ -258,7 +258,7 @@ async function refresh() { } ``` -यो खाता डेटा अपडेट गर्छ, त्यसपछि ड्यासबोर्ड पेजको HTML अपडेट गर्ने काम गर्छ। यो ड्यासबोर्ड रूट लोड हुँदा हामीले कल गर्न आवश्यक छ। रूट परिभाषा अपडेट गर्नुहोस्: +यसले खाता डेटा अद्यावधिक गर्छ, त्यसपछि ड्यासबोर्ड पृष्ठको HTML अद्यावधिक गर्ने ख्याल राख्छ। यो ड्यासबोर्ड रूट लोड हुँदा हामीले कल गर्नुपर्ने कुरा हो। रूट परिभाषालाई यससँग अद्यावधिक गर्नुहोस्: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -अब ड्यासबोर्ड रिफ्रेस गर्ने प्रयास गर्नुहोस्, यसले अपडेट गरिएको खाता डेटा देखाउनु पर्छ। +अब ड्यासबोर्ड रिफ्रेस गर्ने प्रयास गर्नुहोस्, यसले अद्यावधिक गरिएको खाता डेटा देखाउनु पर्छ। --- ## 🚀 चुनौती -अब हामीले ड्यासबोर्ड लोड हुँदा हरेक पटक खाता डेटा पुनः लोड गर्छौं, के तपाईं सोच्नुहुन्छ कि हामीले *सबै खाता* डेटा कायम राख्न अझै आवश्यक छ? +अब हामीले ड्यासबोर्ड लोड हुँदा हरेक पटक खाता डेटा पुनः लोड गर्छौं, के तपाईंलाई लाग्छ कि हामीले *सबै खाता* डेटा कायम राख्न अझै आवश्यक छ? -`localStorage` बाट बचत र लोड गरिने कुरालाई एप काम गर्न आवश्यक पर्ने कुरामा मात्र सीमित गर्न प्रयास गर्नुहोस्। +`localStorage` बाट केवल एप काम गर्नको लागि पूर्ण रूपमा आवश्यक पर्ने कुरा मात्र भण्डारण र लोड गर्न परिवर्तन गर्न मिलेर काम गर्ने प्रयास गर्नुहोस्। ## पोस्ट-लेक्चर क्विज - -[पोस्ट-लेक्चर क्विज](https://ff-quizzes.netlify.app/web/quiz/48) +[पोस्ट-व्याख्यान क्विज](https://ff-quizzes.netlify.app/web/quiz/48) ## असाइनमेन्ट -[Implement "Add transaction" dialog](assignment.md) -यहाँ कार्य पूरा गरेपछि प्राप्त हुने उदाहरण परिणाम: +["लेनदेन थप्नुहोस्" संवाद कार्यान्वयन गर्नुहोस्](assignment.md) + +असाइनमेन्ट पूरा गरेपछि प्राप्त हुने उदाहरण परिणाम यहाँ छ: -![Screenshot showing an example "Add transaction" dialog](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.ne.png) +!["लेनदेन थप्नुहोस्" संवादको उदाहरण देखाउँदै स्क्रिनसट](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.ne.png) --- **अस्वीकरण**: -यो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरेर अनुवाद गरिएको छ। हामी यथार्थताको लागि प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छ। यसको मूल भाषा मा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीको लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुने छैनौं। \ No newline at end of file +यो दस्तावेज़ AI अनुवाद सेवा [Co-op Translator](https://github.com/Azure/co-op-translator) प्रयोग गरेर अनुवाद गरिएको हो। हामी यथार्थताको लागि प्रयास गर्छौं, तर कृपया ध्यान दिनुहोस् कि स्वचालित अनुवादमा त्रुटिहरू वा अशुद्धताहरू हुन सक्छ। यसको मूल भाषा मा रहेको मूल दस्तावेज़लाई आधिकारिक स्रोत मानिनुपर्छ। महत्वपूर्ण जानकारीको लागि, व्यावसायिक मानव अनुवाद सिफारिस गरिन्छ। यस अनुवादको प्रयोगबाट उत्पन्न हुने कुनै पनि गलतफहमी वा गलत व्याख्याको लागि हामी जिम्मेवार हुनेछैनौं। \ No newline at end of file diff --git a/translations/nl/7-bank-project/4-state-management/README.md b/translations/nl/7-bank-project/4-state-management/README.md index 5ef5c9569..f957e1aad 100644 --- a/translations/nl/7-bank-project/4-state-management/README.md +++ b/translations/nl/7-bank-project/4-state-management/README.md @@ -1,29 +1,29 @@ -# Bouw een Bankapp Deel 4: Concepten van State Management +# Een Banking App Bouwen Deel 4: Concepten van State Management -## Quiz vóór de les +## Pre-Lecture Quiz -[Quiz vóór de les](https://ff-quizzes.netlify.app/web/quiz/47) +[Pre-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/47) ### Introductie -Naarmate een webapplicatie groeit, wordt het steeds moeilijker om alle datastromen bij te houden. Welke code haalt de data op, welke pagina gebruikt het, waar en wanneer moet het worden bijgewerkt... Het is makkelijk om te eindigen met rommelige code die moeilijk te onderhouden is. Dit geldt vooral wanneer je data moet delen tussen verschillende pagina's van je app, zoals gebruikersgegevens. Het concept van *state management* heeft altijd bestaan in allerlei soorten programma's, maar nu webapps steeds complexer worden, is het een belangrijk punt om over na te denken tijdens de ontwikkeling. +Naarmate een webapplicatie groeit, wordt het steeds moeilijker om alle datastromen bij te houden. Welke code haalt de data op, welke pagina gebruikt het, waar en wanneer moet het worden bijgewerkt... Het is gemakkelijk om te eindigen met rommelige code die moeilijk te onderhouden is. Dit geldt vooral wanneer je gegevens moet delen tussen verschillende pagina's van je app, zoals gebruikersgegevens. Het concept van *state management* heeft altijd bestaan in allerlei soorten programma's, maar nu webapps steeds complexer worden, is het een belangrijk punt om over na te denken tijdens de ontwikkeling. -In dit laatste deel bekijken we de app die we hebben gebouwd opnieuw om te heroverwegen hoe de state wordt beheerd. Dit maakt ondersteuning voor browserverversingen op elk moment mogelijk en zorgt ervoor dat gegevens behouden blijven tussen gebruikerssessies. +In dit laatste deel bekijken we de app die we hebben gebouwd om opnieuw na te denken over hoe de state wordt beheerd, zodat ondersteuning voor browserverversing op elk moment mogelijk is en gegevens behouden blijven tussen gebruikerssessies. ### Vereisten -Je moet het [data ophalen](../3-data/README.md) deel van de webapp hebben voltooid voor deze les. Je moet ook [Node.js](https://nodejs.org) installeren en de [server-API](../api/README.md) lokaal uitvoeren, zodat je accountgegevens kunt beheren. +Je moet het [data ophalen](../3-data/README.md) deel van de webapp hebben voltooid voor deze les. Je moet ook [Node.js](https://nodejs.org) installeren en [de server-API](../api/README.md) lokaal uitvoeren, zodat je accountgegevens kunt beheren. -Je kunt controleren of de server correct werkt door dit commando in een terminal uit te voeren: +Je kunt testen of de server correct werkt door dit commando in een terminal uit te voeren: ```sh curl http://localhost:5000/api @@ -32,17 +32,17 @@ curl http://localhost:5000/api --- -## State management heroverwegen +## Herziening van state management -In de [vorige les](../3-data/README.md) hebben we een basisconcept van state in onze app geïntroduceerd met de globale `account`-variabele die de bankgegevens bevat van de momenteel ingelogde gebruiker. Onze huidige implementatie heeft echter enkele tekortkomingen. Probeer de pagina te verversen terwijl je op het dashboard bent. Wat gebeurt er? +In de [vorige les](../3-data/README.md) introduceerden we een basisconcept van state in onze app met de globale `account`-variabele die de bankgegevens bevat van de momenteel ingelogde gebruiker. Onze huidige implementatie heeft echter enkele tekortkomingen. Probeer de pagina te verversen terwijl je op het dashboard bent. Wat gebeurt er? Er zijn drie problemen met de huidige code: -- De state wordt niet behouden, want een browserverversing brengt je terug naar de inlogpagina. -- Er zijn meerdere functies die de state wijzigen. Naarmate de app groeit, kan dit het moeilijk maken om de wijzigingen bij te houden en is het makkelijk om te vergeten iets bij te werken. +- De state wordt niet behouden, omdat een browserverversing je terugbrengt naar de inlogpagina. +- Er zijn meerdere functies die de state wijzigen. Naarmate de app groeit, kan dit het moeilijk maken om de wijzigingen bij te houden en is het gemakkelijk om te vergeten een update uit te voeren. - De state wordt niet opgeruimd, dus wanneer je op *Uitloggen* klikt, blijven de accountgegevens aanwezig, zelfs als je op de inlogpagina bent. -We zouden onze code kunnen bijwerken om deze problemen één voor één aan te pakken, maar dat zou leiden tot meer code duplicatie en de app complexer en moeilijker te onderhouden maken. Of we kunnen even pauzeren en onze strategie heroverwegen. +We zouden onze code kunnen bijwerken om deze problemen één voor één aan te pakken, maar dat zou meer code duplicatie creëren en de app complexer en moeilijker te onderhouden maken. Of we kunnen een paar minuten pauzeren en onze strategie heroverwegen. > Welke problemen proberen we hier echt op te lossen? @@ -51,17 +51,17 @@ We zouden onze code kunnen bijwerken om deze problemen één voor één aan te p - Hoe houden we de datastromen in een app begrijpelijk? - Hoe zorgen we ervoor dat de state data altijd synchroon loopt met de gebruikersinterface (en vice versa)? -Als je deze problemen hebt aangepakt, zijn andere problemen die je mogelijk hebt, of al opgelost, of makkelijker op te lossen. Er zijn veel mogelijke benaderingen om deze problemen op te lossen, maar wij kiezen voor een veelgebruikte oplossing die bestaat uit **het centraliseren van de data en de manieren om deze te wijzigen**. De datastromen zouden er als volgt uitzien: +Als je deze hebt aangepakt, zijn eventuele andere problemen die je hebt mogelijk al opgelost of gemakkelijker op te lossen. Er zijn veel mogelijke benaderingen om deze problemen op te lossen, maar we kiezen voor een veelgebruikte oplossing die bestaat uit **het centraliseren van de data en de manieren om deze te wijzigen**. De datastromen zouden er als volgt uitzien: -![Schema dat de datastromen tussen de HTML, gebruikersacties en state toont](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.nl.png) +![Schema dat de datastromen toont tussen de HTML, gebruikersacties en state](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.nl.png) -> We behandelen hier niet het deel waarin de data automatisch de weergave bijwerkt, omdat dit gekoppeld is aan meer geavanceerde concepten van [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming). Dit is een goed vervolgonderwerp als je een diepere duik wilt nemen. +> We behandelen hier niet het deel waarin de data automatisch de weergave-update triggert, omdat dit gekoppeld is aan meer geavanceerde concepten van [Reactive Programming](https://en.wikipedia.org/wiki/Reactive_programming). Dit is een goed onderwerp om verder in te duiken als je er klaar voor bent. ✅ Er zijn veel bibliotheken met verschillende benaderingen voor state management, waarbij [Redux](https://redux.js.org) een populaire optie is. Bekijk de concepten en patronen die worden gebruikt, omdat dit vaak een goede manier is om te leren welke potentiële problemen je kunt tegenkomen in grote webapps en hoe deze kunnen worden opgelost. ### Taak -We beginnen met een beetje refactoring. Vervang de `account`-declaratie: +We beginnen met een beetje refactoring. Vervang de `account`-verklaring: ```js let account = null; @@ -75,31 +75,31 @@ let state = { }; ``` -Het idee is om *alle app-data te centraliseren* in een enkel state-object. Voor nu hebben we alleen `account` in de state, dus het verandert niet veel, maar het creëert een basis voor toekomstige uitbreidingen. +Het idee is om *alle app-data te centraliseren* in een enkel state-object. We hebben momenteel alleen `account` in de state, dus het verandert niet veel, maar het creëert een pad voor toekomstige uitbreidingen. -We moeten ook de functies die het gebruiken bijwerken. Vervang in de functies `register()` en `login()` `account = ...` door `state.account = ...`; +We moeten ook de functies bijwerken die het gebruiken. Vervang in de `register()`- en `login()`-functies `account = ...` door `state.account = ...`; -Voeg aan het begin van de functie `updateDashboard()` deze regel toe: +Voeg aan het begin van de `updateDashboard()`-functie deze regel toe: ```js const account = state.account; ``` -Deze refactoring op zichzelf brengt niet veel verbeteringen, maar het idee was om de basis te leggen voor de volgende wijzigingen. +Deze refactoring op zichzelf heeft niet veel verbeteringen gebracht, maar het idee was om de basis te leggen voor de volgende wijzigingen. ## Gegevenswijzigingen bijhouden -Nu we het `state`-object hebben geïntroduceerd om onze data op te slaan, is de volgende stap om de updates te centraliseren. Het doel is om het makkelijker te maken om wijzigingen en wanneer ze plaatsvinden bij te houden. +Nu we het `state`-object hebben geïntroduceerd om onze gegevens op te slaan, is de volgende stap om de updates te centraliseren. Het doel is om het gemakkelijker te maken om eventuele wijzigingen en wanneer ze plaatsvinden bij te houden. -Om te voorkomen dat wijzigingen worden aangebracht in het `state`-object, is het ook een goede gewoonte om het te beschouwen als [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), wat betekent dat het helemaal niet kan worden gewijzigd. Dit betekent ook dat je een nieuw state-object moet maken als je iets wilt wijzigen. Door dit te doen, bouw je een bescherming tegen mogelijk ongewenste [bijwerkingen](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) en open je mogelijkheden voor nieuwe functies in je app, zoals het implementeren van ongedaan maken/herhalen, terwijl het ook makkelijker wordt om te debuggen. Bijvoorbeeld, je zou elke wijziging in de state kunnen loggen en een geschiedenis van de wijzigingen kunnen bijhouden om de bron van een bug te begrijpen. +Om te voorkomen dat wijzigingen worden aangebracht in het `state`-object, is het ook een goede gewoonte om het te beschouwen als [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), wat betekent dat het helemaal niet kan worden gewijzigd. Dit betekent ook dat je een nieuw state-object moet maken als je iets wilt wijzigen. Door dit te doen, bouw je een bescherming tegen mogelijk ongewenste [bijwerkingen](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) en open je mogelijkheden voor nieuwe functies in je app, zoals het implementeren van undo/redo, terwijl het ook gemakkelijker wordt om te debuggen. Bijvoorbeeld, je zou elke wijziging in de state kunnen loggen en een geschiedenis van de wijzigingen kunnen bijhouden om de bron van een bug te begrijpen. -In JavaScript kun je [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) gebruiken om een onveranderlijke versie van een object te maken. Als je probeert wijzigingen aan te brengen in een onveranderlijk object, wordt er een uitzondering gegenereerd. +In JavaScript kun je [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) gebruiken om een immutable versie van een object te maken. Als je probeert wijzigingen aan te brengen in een immutable object, wordt er een uitzondering gegenereerd. -✅ Weet je het verschil tussen een *oppervlakkig* en een *diep* onveranderlijk object? Je kunt erover lezen [hier](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Ken je het verschil tussen een *shallow* en een *deep* immutable object? Je kunt er [hier](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) meer over lezen. ### Taak -Laten we een nieuwe functie `updateState()` maken: +Laten we een nieuwe `updateState()`-functie maken: ```js function updateState(property, newData) { @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -In deze functie maken we een nieuw state-object en kopiëren we data van de vorige state met behulp van de [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Vervolgens overschrijven we een specifieke eigenschap van het state-object met de nieuwe data met behulp van de [bracket notatie](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` voor toewijzing. Tot slot vergrendelen we het object om wijzigingen te voorkomen met `Object.freeze()`. Voor nu hebben we alleen de `account`-eigenschap opgeslagen in de state, maar met deze aanpak kun je zoveel eigenschappen toevoegen als je nodig hebt. +In deze functie maken we een nieuw state-object en kopiëren we gegevens van de vorige state met behulp van de [*spread (`...`) operator*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Vervolgens overschrijven we een specifieke eigenschap van het state-object met de nieuwe gegevens met behulp van de [bracket notatie](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` voor toewijzing. Ten slotte vergrendelen we het object om wijzigingen te voorkomen met `Object.freeze()`. We hebben momenteel alleen de `account`-eigenschap opgeslagen in de state, maar met deze aanpak kun je zoveel eigenschappen toevoegen als je nodig hebt. We zullen ook de `state`-initialisatie bijwerken om ervoor te zorgen dat de initiële state ook bevroren is: @@ -132,7 +132,7 @@ Doe hetzelfde met de `login`-functie, vervang `state.account = data;` door: updateState('account', data); ``` -We grijpen nu de kans om het probleem op te lossen waarbij accountgegevens niet worden gewist wanneer de gebruiker op *Uitloggen* klikt. +We nemen nu de kans om het probleem op te lossen waarbij accountgegevens niet worden gewist wanneer de gebruiker op *Uitloggen* klikt. Maak een nieuwe functie `logout()`: @@ -143,31 +143,31 @@ function logout() { } ``` -Vervang in `updateDashboard()` de omleiding `return navigate('/login');` door `return logout();` +Vervang in `updateDashboard()` de omleiding `return navigate('/login');` door `return logout()`; Probeer een nieuw account te registreren, uit te loggen en opnieuw in te loggen om te controleren of alles nog steeds correct werkt. -> Tip: je kunt alle state-wijzigingen bekijken door `console.log(state)` toe te voegen onderaan `updateState()` en de console in de ontwikkelaarstools van je browser te openen. +> Tip: je kunt alle state-wijzigingen bekijken door `console.log(state)` toe te voegen onderaan `updateState()` en de console te openen in de ontwikkeltools van je browser. ## De state behouden -De meeste webapps moeten gegevens behouden om correct te kunnen werken. Alle kritieke gegevens worden meestal opgeslagen in een database en benaderd via een server-API, zoals de gebruikersaccountgegevens in ons geval. Maar soms is het ook interessant om bepaalde gegevens op te slaan in de client-app die in je browser draait, voor een betere gebruikerservaring of om de laadtijd te verbeteren. +De meeste webapps moeten gegevens behouden om correct te kunnen werken. Alle kritieke gegevens worden meestal opgeslagen in een database en benaderd via een server-API, zoals de gebruikersaccountgegevens in ons geval. Maar soms is het ook interessant om enkele gegevens te behouden in de client-app die in je browser draait, voor een betere gebruikerservaring of om de laadsnelheid te verbeteren. -Wanneer je gegevens in je browser wilt opslaan, zijn er een paar belangrijke vragen die je jezelf moet stellen: +Wanneer je gegevens wilt behouden in je browser, zijn er een paar belangrijke vragen die je jezelf moet stellen: - *Zijn de gegevens gevoelig?* Je moet vermijden om gevoelige gegevens op de client op te slaan, zoals gebruikerswachtwoorden. - *Hoe lang moet je deze gegevens bewaren?* Wil je deze gegevens alleen voor de huidige sessie gebruiken of wil je dat ze voor altijd worden opgeslagen? -Er zijn meerdere manieren om informatie op te slaan in een webapp, afhankelijk van wat je wilt bereiken. Bijvoorbeeld, je kunt de URL's gebruiken om een zoekopdracht op te slaan en deze deelbaar te maken tussen gebruikers. Je kunt ook [HTTP-cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) gebruiken als de gegevens moeten worden gedeeld met de server, zoals [authenticatie](https://en.wikipedia.org/wiki/Authentication) informatie. +Er zijn meerdere manieren om informatie binnen een webapp op te slaan, afhankelijk van wat je wilt bereiken. Bijvoorbeeld, je kunt de URL's gebruiken om een zoekopdracht op te slaan en deze deelbaar te maken tussen gebruikers. Je kunt ook [HTTP-cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) gebruiken als de gegevens moeten worden gedeeld met de server, zoals [authenticatie](https://en.wikipedia.org/wiki/Authentication) informatie. Een andere optie is om een van de vele browser-API's te gebruiken voor het opslaan van gegevens. Twee daarvan zijn bijzonder interessant: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): een [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) waarmee je gegevens specifiek voor de huidige website kunt behouden over verschillende sessies. De opgeslagen gegevens verlopen nooit. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): dit werkt hetzelfde als `localStorage`, behalve dat de opgeslagen gegevens worden gewist wanneer de sessie eindigt (wanneer de browser wordt gesloten). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): een [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) waarmee gegevens specifiek voor de huidige website kunnen worden behouden tussen verschillende sessies. De opgeslagen gegevens verlopen nooit. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): deze werkt hetzelfde als `localStorage`, behalve dat de opgeslagen gegevens worden gewist wanneer de sessie eindigt (wanneer de browser wordt gesloten). -Merk op dat beide API's alleen [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) kunnen opslaan. Als je complexe objecten wilt opslaan, moet je ze serialiseren naar het [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formaat met [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Let op dat beide API's alleen [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) kunnen opslaan. Als je complexe objecten wilt opslaan, moet je ze serialiseren naar het [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formaat met [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Als je een webapp wilt maken die niet met een server werkt, is het ook mogelijk om een database op de client te maken met behulp van de [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Dit is gereserveerd voor geavanceerde gebruiksscenario's of als je een aanzienlijke hoeveelheid gegevens moet opslaan, omdat het complexer is om te gebruiken. +✅ Als je een webapp wilt maken die niet met een server werkt, is het ook mogelijk om een database op de client te maken met de [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Deze is gereserveerd voor geavanceerde gebruiksscenario's of als je een aanzienlijke hoeveelheid gegevens moet opslaan, omdat het complexer is om te gebruiken. ### Taak @@ -183,9 +183,9 @@ Voeg vervolgens deze regel toe aan het einde van de `updateState()`-functie: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Hiermee worden de gebruikersaccountgegevens opgeslagen en altijd up-to-date gehouden, omdat we eerder alle state-updates hebben gecentraliseerd. Dit is waar we beginnen te profiteren van al onze eerdere refactors 🙂. +Hiermee worden de gebruikersaccountgegevens behouden en altijd up-to-date gehouden, omdat we eerder alle state-updates hebben gecentraliseerd. Dit is waar we beginnen te profiteren van al onze eerdere refactors 🙂. -Omdat de gegevens worden opgeslagen, moeten we ook zorgen voor het herstellen ervan wanneer de app wordt geladen. Aangezien we meer initialisatiecode beginnen te krijgen, is het misschien een goed idee om een nieuwe `init`-functie te maken, die ook onze eerdere code onderaan `app.js` bevat: +Omdat de gegevens worden opgeslagen, moeten we ook zorgen voor het herstellen ervan wanneer de app wordt geladen. Aangezien we meer initialisatiecode beginnen te krijgen, kan het een goed idee zijn om een nieuwe `init`-functie te maken, die ook onze eerdere code onderaan `app.js` bevat: ```js function init() { @@ -202,11 +202,11 @@ function init() { init(); ``` -Hier halen we de opgeslagen gegevens op, en als er gegevens zijn, werken we de state dienovereenkomstig bij. Het is belangrijk om dit *voordat* de route wordt bijgewerkt te doen, omdat er mogelijk code is die afhankelijk is van de state tijdens de pagina-update. +Hier halen we de opgeslagen gegevens op, en als er gegevens zijn, werken we de state dienovereenkomstig bij. Het is belangrijk om dit *voor* het bijwerken van de route te doen, omdat er mogelijk code is die afhankelijk is van de state tijdens de pagina-update. -We kunnen ook de *Dashboard*-pagina de standaardpagina van onze applicatie maken, aangezien we nu de accountgegevens behouden. Als er geen gegevens worden gevonden, zorgt het dashboard er toch voor dat je wordt doorgestuurd naar de *Inlog*-pagina. Vervang in `updateRoute()` de fallback `return navigate('/login');` door `return navigate('/dashboard');`. +We kunnen ook de *Dashboard*-pagina de standaardpagina van onze applicatie maken, omdat we nu de accountgegevens behouden. Als er geen gegevens worden gevonden, zorgt het dashboard ervoor dat het doorverwijst naar de *Inloggen*-pagina. Vervang in `updateRoute()` de fallback `return navigate('/login');` door `return navigate('/dashboard');`. -Log nu in op de app en probeer de pagina te verversen. Je zou op het dashboard moeten blijven. Met die update hebben we al onze initiële problemen opgelost... +Log nu in op de app en probeer de pagina te verversen. Je zou op het dashboard moeten blijven. Met die update hebben we alle oorspronkelijke problemen opgelost... ## De gegevens verversen @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Probeer nu de dashboardpagina in de browser te verversen. Wat gebeurt er? Zie je de nieuwe transactie? +Probeer nu je dashboardpagina in de browser te verversen. Wat gebeurt er? Zie je de nieuwe transactie? -De state wordt dankzij de `localStorage` voor onbepaalde tijd behouden, maar dat betekent ook dat deze nooit wordt bijgewerkt totdat je uitlogt en opnieuw inlogt! +De state wordt onbeperkt behouden dankzij de `localStorage`, maar dat betekent ook dat deze nooit wordt bijgewerkt totdat je uitlogt en opnieuw inlogt! -Een mogelijke strategie om dit op te lossen is om de accountgegevens elke keer dat het dashboard wordt geladen opnieuw te laden, om verouderde gegevens te voorkomen. +Een mogelijke strategie om dat op te lossen is om de accountgegevens opnieuw te laden telkens wanneer het dashboard wordt geladen, om verouderde gegevens te voorkomen. ### Taak @@ -258,7 +258,7 @@ async function refresh() { } ``` -Deze functie werkt de accountgegevens bij en zorgt er vervolgens voor dat de HTML van de dashboardpagina wordt bijgewerkt. Dit is wat we moeten aanroepen wanneer de dashboardroute wordt geladen. Werk de routedefinitie bij met: +Deze functie werkt de accountgegevens bij en zorgt vervolgens voor het bijwerken van de HTML van de dashboardpagina. Dit is wat we moeten aanroepen wanneer de dashboardroute wordt geladen. Werk de routedefinitie bij met: ```js const routes = { @@ -273,22 +273,22 @@ Probeer nu het dashboard te verversen, het zou de bijgewerkte accountgegevens mo ## 🚀 Uitdaging -Nu we de accountgegevens elke keer dat het dashboard wordt geladen opnieuw ophalen, denk je dat we nog steeds *alle accountgegevens* moeten behouden? +Nu we de accountgegevens opnieuw laden telkens wanneer het dashboard wordt geladen, denk je dat we nog steeds *alle accountgegevens* moeten behouden? -Probeer samen te werken om te wijzigen wat wordt opgeslagen en geladen vanuit `localStorage`, zodat alleen wordt opgeslagen wat absoluut noodzakelijk is voor de app om te werken. - -## Quiz na de les +Probeer samen te werken om te veranderen wat wordt opgeslagen en geladen vanuit `localStorage` zodat alleen wordt opgenomen wat absoluut nodig is voor de app om te werken. +## Post-Lecture Quiz [Quiz na de les](https://ff-quizzes.netlify.app/web/quiz/48) ## Opdracht -[Implementeer "Transactie toevoegen" dialoogvenster](assignment.md) -Hier is een voorbeeldresultaat na het voltooien van de opdracht: +[Implementeer de dialoog "Transactie toevoegen"](assignment.md) + +Hier is een voorbeeld van het resultaat na het voltooien van de opdracht: -![Schermafbeelding met een voorbeeld van het dialoogvenster "Transactie toevoegen"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.nl.png) +![Screenshot met een voorbeeld van de dialoog "Transactie toevoegen"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.nl.png) --- **Disclaimer**: -Dit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor kritieke informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling. \ No newline at end of file +Dit document is vertaald met behulp van de AI-vertalingsservice [Co-op Translator](https://github.com/Azure/co-op-translator). Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling. \ No newline at end of file diff --git a/translations/no/7-bank-project/4-state-management/README.md b/translations/no/7-bank-project/4-state-management/README.md index 20f47cda6..594d53045 100644 --- a/translations/no/7-bank-project/4-state-management/README.md +++ b/translations/no/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Construir uma App Bancária Parte 4: Conceitos de Gestão de Estado +# Criar uma App Bancária Parte 4: Conceitos de Gestão de Estado ## Questionário Pré-Aula @@ -15,9 +15,9 @@ CO_OP_TRANSLATOR_METADATA: ### Introdução -À medida que uma aplicação web cresce, torna-se um desafio acompanhar todos os fluxos de dados. Qual código obtém os dados, qual página os consome, onde e quando precisam ser atualizados... é fácil acabar com um código confuso e difícil de manter. Isso é especialmente verdadeiro quando é necessário compartilhar dados entre diferentes páginas da aplicação, como os dados do utilizador. O conceito de *gestão de estado* sempre existiu em todos os tipos de programas, mas à medida que as aplicações web continuam a crescer em complexidade, tornou-se um ponto-chave a considerar durante o desenvolvimento. +À medida que uma aplicação web cresce, torna-se um desafio acompanhar todos os fluxos de dados. Que código obtém os dados, que página os consome, onde e quando precisam ser atualizados... é fácil acabar com um código desorganizado e difícil de manter. Isto é especialmente verdade quando é necessário partilhar dados entre diferentes páginas da aplicação, como os dados do utilizador. O conceito de *gestão de estado* sempre existiu em todos os tipos de programas, mas à medida que as aplicações web continuam a crescer em complexidade, tornou-se um ponto-chave a considerar durante o desenvolvimento. -Nesta última parte, vamos rever a aplicação que construímos para repensar como o estado é gerido, permitindo suporte para atualizações do navegador a qualquer momento e persistindo os dados entre sessões do utilizador. +Nesta última parte, vamos rever a aplicação que construímos para repensar como o estado é gerido, permitindo suporte para atualizações do navegador em qualquer momento e persistindo os dados entre sessões de utilizador. ### Pré-requisitos @@ -34,28 +34,28 @@ curl http://localhost:5000/api ## Repensar a gestão de estado -Na [lição anterior](../3-data/README.md), introduzimos um conceito básico de estado na nossa aplicação com a variável global `account`, que contém os dados bancários do utilizador atualmente autenticado. No entanto, a nossa implementação atual tem algumas falhas. Experimente atualizar a página enquanto está no painel. O que acontece? +Na [lição anterior](../3-data/README.md), introduzimos um conceito básico de estado na nossa aplicação com a variável global `account`, que contém os dados bancários do utilizador atualmente autenticado. No entanto, a nossa implementação atual tem algumas falhas. Experimente atualizar a página quando estiver no painel de controlo. O que acontece? Há 3 problemas com o código atual: - O estado não é persistido, pois uma atualização do navegador leva-o de volta à página de login. -- Existem várias funções que modificam o estado. À medida que a aplicação cresce, isso pode dificultar o acompanhamento das alterações e é fácil esquecer de atualizar algo. -- O estado não é limpo, então, quando clica em *Logout*, os dados da conta ainda estão lá, mesmo estando na página de login. +- Existem várias funções que modificam o estado. À medida que a aplicação cresce, pode tornar-se difícil acompanhar as alterações e é fácil esquecer de atualizar algo. +- O estado não é limpo, então quando clica em *Logout*, os dados da conta ainda estão lá, mesmo estando na página de login. -Poderíamos atualizar o nosso código para resolver esses problemas um por um, mas isso criaria mais duplicação de código e tornaria a aplicação mais complexa e difícil de manter. Ou poderíamos parar por alguns minutos e repensar a nossa estratégia. +Poderíamos atualizar o nosso código para resolver estes problemas um por um, mas isso criaria mais duplicação de código e tornaria a aplicação mais complexa e difícil de manter. Ou poderíamos parar por alguns minutos e repensar a nossa estratégia. > Que problemas estamos realmente a tentar resolver aqui? -[A gestão de estado](https://en.wikipedia.org/wiki/State_management) trata de encontrar uma abordagem eficaz para resolver estes dois problemas específicos: +[Gestão de estado](https://en.wikipedia.org/wiki/State_management) trata de encontrar uma abordagem eficaz para resolver estes dois problemas específicos: - Como manter os fluxos de dados numa aplicação compreensíveis? -- Como garantir que os dados do estado estejam sempre sincronizados com a interface do utilizador (e vice-versa)? +- Como manter os dados de estado sempre sincronizados com a interface do utilizador (e vice-versa)? -Depois de resolver esses problemas, quaisquer outros problemas que possa ter podem já estar resolvidos ou tornarem-se mais fáceis de resolver. Existem muitas abordagens possíveis para resolver esses problemas, mas vamos optar por uma solução comum que consiste em **centralizar os dados e as formas de os alterar**. Os fluxos de dados seriam assim: +Depois de resolver estes problemas, quaisquer outros que possam surgir podem já estar resolvidos ou tornar-se mais fáceis de resolver. Existem muitas abordagens possíveis para resolver estes problemas, mas vamos optar por uma solução comum que consiste em **centralizar os dados e as formas de os alterar**. Os fluxos de dados seriam assim: ![Esquema mostrando os fluxos de dados entre o HTML, ações do utilizador e estado](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.pt.png) -> Não vamos abordar aqui a parte em que os dados automaticamente desencadeiam a atualização da vista, pois está ligada a conceitos mais avançados de [Programação Reativa](https://en.wikipedia.org/wiki/Reactive_programming). É um bom tema para explorar mais a fundo. +> Não vamos abordar aqui a parte em que os dados atualizam automaticamente a visualização, pois está ligada a conceitos mais avançados de [Programação Reativa](https://en.wikipedia.org/wiki/Reactive_programming). É um bom tema para explorar mais a fundo. ✅ Existem muitas bibliotecas com diferentes abordagens para gestão de estado, sendo o [Redux](https://redux.js.org) uma opção popular. Dê uma olhada nos conceitos e padrões utilizados, pois muitas vezes é uma boa forma de aprender sobre os potenciais problemas que pode enfrentar em grandes aplicações web e como podem ser resolvidos. @@ -91,9 +91,9 @@ Esta refatoração por si só não trouxe muitas melhorias, mas a ideia era prep Agora que implementámos o objeto `state` para armazenar os dados, o próximo passo é centralizar as atualizações. O objetivo é facilitar o acompanhamento de quaisquer alterações e quando elas ocorrem. -Para evitar alterações feitas diretamente no objeto `state`, também é uma boa prática considerá-lo [*imutável*](https://en.wikipedia.org/wiki/Immutable_object), o que significa que não pode ser modificado de forma alguma. Isso também significa que é necessário criar um novo objeto de estado se quiser alterar algo nele. Ao fazer isso, constrói uma proteção contra potenciais [efeitos colaterais](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) indesejados e abre possibilidades para novas funcionalidades na aplicação, como implementar desfazer/refazer, além de facilitar a depuração. Por exemplo, poderia registar todas as alterações feitas no estado e manter um histórico das alterações para entender a origem de um erro. +Para evitar que sejam feitas alterações diretamente ao objeto `state`, também é uma boa prática considerá-lo [*imutável*](https://en.wikipedia.org/wiki/Immutable_object), o que significa que não pode ser modificado de forma alguma. Isso também implica que é necessário criar um novo objeto de estado se quiser alterar algo nele. Ao fazer isso, constrói-se uma proteção contra potenciais [efeitos colaterais](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) indesejados e abre-se possibilidades para novas funcionalidades na aplicação, como implementar desfazer/refazer, além de facilitar a depuração. Por exemplo, poderia registar todas as alterações feitas ao estado e manter um histórico das alterações para entender a origem de um erro. -Em JavaScript, pode usar [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) para criar uma versão imutável de um objeto. Se tentar fazer alterações num objeto imutável, será lançada uma exceção. +Em JavaScript, pode usar [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) para criar uma versão imutável de um objeto. Se tentar fazer alterações a um objeto imutável, será gerada uma exceção. ✅ Sabe a diferença entre um objeto imutável *superficial* e *profundo*? Pode ler sobre isso [aqui](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Nesta função, estamos a criar um novo objeto de estado e a copiar os dados do estado anterior usando o [*operador de espalhamento (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Em seguida, substituímos uma propriedade específica do objeto de estado com os novos dados usando a [notação de colchetes](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` para atribuição. Por fim, bloqueamos o objeto para evitar modificações usando `Object.freeze()`. Por enquanto, só temos a propriedade `account` armazenada no estado, mas com esta abordagem pode adicionar quantas propriedades forem necessárias. +Nesta função, estamos a criar um novo objeto de estado e a copiar os dados do estado anterior usando o [*operador de espalhamento (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Depois, substituímos uma propriedade específica do objeto de estado com os novos dados usando a [notação de colchetes](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` para atribuição. Por fim, bloqueamos o objeto para evitar modificações usando `Object.freeze()`. Por enquanto, só temos a propriedade `account` armazenada no estado, mas com esta abordagem pode adicionar quantas propriedades forem necessárias. Também vamos atualizar a inicialização do `state` para garantir que o estado inicial também seja congelado: @@ -143,7 +143,7 @@ function logout() { } ``` -Na função `updateDashboard()`, substitua o redirecionamento `return navigate('/login');` por `return logout();`; +Na função `updateDashboard()`, substitua a redireção `return navigate('/login');` por `return logout()`; Experimente registar uma nova conta, fazer logout e login novamente para verificar se tudo ainda funciona corretamente. @@ -151,21 +151,21 @@ Experimente registar uma nova conta, fazer logout e login novamente para verific ## Persistir o estado -A maioria das aplicações web precisa de persistir dados para funcionar corretamente. Todos os dados críticos geralmente são armazenados numa base de dados e acessados através de uma API de servidor, como os dados da conta do utilizador no nosso caso. Mas, às vezes, também é interessante persistir alguns dados na aplicação cliente que está a ser executada no navegador, para uma melhor experiência do utilizador ou para melhorar o desempenho de carregamento. +A maioria das aplicações web precisa de persistir dados para funcionar corretamente. Todos os dados críticos geralmente são armazenados numa base de dados e acessados através de uma API de servidor, como os dados da conta de utilizador no nosso caso. Mas, por vezes, também é interessante persistir alguns dados na aplicação cliente que está a ser executada no navegador, para uma melhor experiência do utilizador ou para melhorar o desempenho de carregamento. Quando quiser persistir dados no navegador, há algumas perguntas importantes que deve fazer: - *Os dados são sensíveis?* Deve evitar armazenar quaisquer dados sensíveis no cliente, como senhas de utilizador. -- *Por quanto tempo precisa de manter esses dados?* Pretende acessar esses dados apenas durante a sessão atual ou quer que sejam armazenados para sempre? +- *Por quanto tempo precisa de manter estes dados?* Planeia aceder a estes dados apenas durante a sessão atual ou quer que sejam armazenados para sempre? Existem várias formas de armazenar informações numa aplicação web, dependendo do que pretende alcançar. Por exemplo, pode usar os URLs para armazenar uma consulta de pesquisa e torná-la partilhável entre utilizadores. Também pode usar [cookies HTTP](https://developer.mozilla.org/docs/Web/HTTP/Cookies) se os dados precisarem de ser partilhados com o servidor, como informações de [autenticação](https://en.wikipedia.org/wiki/Authentication). Outra opção é usar uma das muitas APIs do navegador para armazenar dados. Duas delas são particularmente interessantes: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): um [armazenamento de chave/valor](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) que permite persistir dados específicos do site atual entre diferentes sessões. Os dados guardados nele nunca expiram. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): um [armazenamento chave/valor](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) que permite persistir dados específicos do site atual entre diferentes sessões. Os dados guardados nele nunca expiram. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): funciona da mesma forma que o `localStorage`, exceto que os dados armazenados nele são apagados quando a sessão termina (quando o navegador é fechado). -Note que ambas as APIs só permitem armazenar [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Se quiser armazenar objetos complexos, terá de os serializar para o formato [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) usando [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Note que ambas estas APIs só permitem armazenar [strings](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Se quiser armazenar objetos complexos, terá de os serializar para o formato [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) usando [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). ✅ Se quiser criar uma aplicação web que não funcione com um servidor, também é possível criar uma base de dados no cliente usando a API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Esta é reservada para casos de uso avançados ou se precisar de armazenar uma quantidade significativa de dados, pois é mais complexa de usar. @@ -183,9 +183,9 @@ Depois, adicione esta linha no final da função `updateState()`: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Com isso, os dados da conta do utilizador serão persistidos e sempre atualizados, já que centralizámos anteriormente todas as atualizações de estado. É aqui que começamos a beneficiar de todas as refatorações anteriores 🙂. +Com isto, os dados da conta do utilizador serão persistidos e sempre atualizados, já que centralizámos anteriormente todas as atualizações de estado. É aqui que começamos a beneficiar de todas as refatorações anteriores 🙂. -Como os dados são guardados, também temos de cuidar da sua restauração quando a aplicação é carregada. Como começaremos a ter mais código de inicialização, pode ser uma boa ideia criar uma nova função `init`, que também inclui o nosso código anterior no final de `app.js`: +Como os dados são guardados, também temos de cuidar de os restaurar quando a aplicação é carregada. Como começaremos a ter mais código de inicialização, pode ser uma boa ideia criar uma nova função `init`, que também inclui o nosso código anterior no final de `app.js`: ```js function init() { @@ -204,15 +204,15 @@ init(); Aqui recuperamos os dados guardados e, se houver algum, atualizamos o estado de acordo. É importante fazer isso *antes* de atualizar a rota, pois pode haver código que depende do estado durante a atualização da página. -Também podemos tornar a página *Dashboard* a página padrão da nossa aplicação, já que agora estamos a persistir os dados da conta. Se nenhum dado for encontrado, o painel cuida de redirecionar para a página de *Login* de qualquer forma. Na função `updateRoute()`, substitua o fallback `return navigate('/login');` por `return navigate('/dashboard');`. +Também podemos tornar a página *Dashboard* a página padrão da nossa aplicação, já que agora estamos a persistir os dados da conta. Se não forem encontrados dados, o painel de controlo encarrega-se de redirecionar para a página de *Login* de qualquer forma. Em `updateRoute()`, substitua o fallback `return navigate('/login');` por `return navigate('/dashboard');`. -Agora faça login na aplicação e experimente atualizar a página. Deve permanecer no painel. Com essa atualização, resolvemos todos os problemas iniciais... +Agora faça login na aplicação e experimente atualizar a página. Deve permanecer no painel de controlo. Com esta atualização, resolvemos todos os problemas iniciais... ## Atualizar os dados ...Mas também podemos ter criado um novo problema. Ups! -Vá ao painel usando a conta `test`, depois execute este comando num terminal para criar uma nova transação: +Vá ao painel de controlo usando a conta `test`, depois execute este comando num terminal para criar uma nova transação: ```sh curl --request POST \ @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Experimente atualizar o painel no navegador agora. O que acontece? Vê a nova transação? +Experimente atualizar a página do painel de controlo no navegador agora. O que acontece? Vê a nova transação? O estado é persistido indefinidamente graças ao `localStorage`, mas isso também significa que nunca é atualizado até sair da aplicação e entrar novamente! -Uma possível estratégia para corrigir isso é recarregar os dados da conta sempre que o painel for carregado, para evitar dados desatualizados. +Uma possível estratégia para corrigir isso é recarregar os dados da conta sempre que o painel de controlo for carregado, para evitar dados desatualizados. ### Tarefa @@ -258,7 +258,7 @@ async function refresh() { } ``` -Esta função atualiza os dados da conta e, em seguida, cuida de atualizar o HTML da página do painel. É o que precisamos de chamar quando a rota do painel for carregada. Atualize a definição da rota com: +Esta função atualiza os dados da conta e, em seguida, cuida de atualizar o HTML da página do painel de controlo. É o que precisamos de chamar quando a rota do painel de controlo for carregada. Atualize a definição da rota com: ```js const routes = { @@ -267,21 +267,21 @@ const routes = { }; ``` -Experimente recarregar o painel agora, deve exibir os dados da conta atualizados. +Experimente recarregar o painel de controlo agora; deve exibir os dados da conta atualizados. --- ## 🚀 Desafio -Agora que recarregamos os dados da conta sempre que o painel é carregado, acha que ainda precisamos de persistir *todos os dados da conta*? +Agora que recarregamos os dados da conta sempre que o painel de controlo é carregado, acha que ainda precisamos de persistir *todos os dados da conta*? -Trabalhe em conjunto para alterar o que é guardado e carregado do `localStorage` para incluir apenas o que é absolutamente necessário para a aplicação funcionar. +Tente trabalhar em conjunto para alterar o que é guardado e carregado do `localStorage` para incluir apenas o que é absolutamente necessário para a aplicação funcionar. ## Questionário Pós-Aula - [Questionário pós-aula](https://ff-quizzes.netlify.app/web/quiz/48) ## Tarefa + [Implementar o diálogo "Adicionar transação"](assignment.md) Aqui está um exemplo do resultado após concluir a tarefa: @@ -290,5 +290,5 @@ Aqui está um exemplo do resultado após concluir a tarefa: --- -**Aviso Legal**: -Este documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos para garantir a precisão, é importante notar que traduções automáticas podem conter erros ou imprecisões. O documento original na sua língua nativa deve ser considerado a fonte autoritária. Para informações críticas, recomenda-se a tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes da utilização desta tradução. \ No newline at end of file +**Aviso**: +Este documento foi traduzido utilizando o serviço de tradução por IA [Co-op Translator](https://github.com/Azure/co-op-translator). Embora nos esforcemos pela precisão, esteja ciente de que traduções automáticas podem conter erros ou imprecisões. O documento original na sua língua nativa deve ser considerado a fonte autoritária. Para informações críticas, recomenda-se uma tradução profissional realizada por humanos. Não nos responsabilizamos por quaisquer mal-entendidos ou interpretações incorretas decorrentes da utilização desta tradução. \ No newline at end of file diff --git a/translations/ro/7-bank-project/4-state-management/README.md b/translations/ro/7-bank-project/4-state-management/README.md index 1816d3173..58dcb7f0c 100644 --- a/translations/ro/7-bank-project/4-state-management/README.md +++ b/translations/ro/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Создание банковского приложения, часть 4: Концепции управления состоянием +# Создание банковского приложения. Часть 4: Понятие управления состоянием -## Предварительный тест +## Тест перед лекцией -[Предварительный тест](https://ff-quizzes.netlify.app/web/quiz/47) +[Тест перед лекцией](https://ff-quizzes.netlify.app/web/quiz/47) ### Введение -По мере роста веб-приложения становится сложнее отслеживать все потоки данных. Какой код получает данные, какая страница их использует, где и когда их нужно обновить... Легко запутаться и получить код, который сложно поддерживать. Это особенно актуально, если нужно делиться данными между различными страницами приложения, например, данными пользователя. Концепция *управления состоянием* всегда существовала во всех типах программ, но с увеличением сложности веб-приложений она стала ключевым моментом, который нужно учитывать при разработке. +По мере роста веб-приложения становится все сложнее отслеживать потоки данных. Какой код получает данные, какая страница их использует, где и когда их нужно обновлять... Легко запутаться в коде, который становится трудно поддерживать. Это особенно актуально, когда нужно делиться данными между разными страницами приложения, например, пользовательскими данными. Концепция *управления состоянием* всегда существовала во всех видах программ, но с ростом сложности веб-приложений она стала ключевым моментом, который необходимо учитывать при разработке. -В этой заключительной части мы пересмотрим наше приложение, чтобы улучшить управление состоянием, обеспечив поддержку обновления браузера в любой момент и сохранение данных между сеансами пользователя. +В этой заключительной части мы пересмотрим приложение, которое мы создали, чтобы улучшить управление состоянием, добавив поддержку обновления браузера в любой момент и сохранение данных между пользовательскими сессиями. ### Предварительные требования -Для этого урока вам нужно завершить часть веб-приложения, посвященную [получению данных](../3-data/README.md). Также необходимо установить [Node.js](https://nodejs.org) и [запустить сервер API](../api/README.md) локально, чтобы управлять данными учетной записи. +Для этого урока вам нужно завершить часть веб-приложения, посвященную [извлечению данных](../3-data/README.md). Также необходимо установить [Node.js](https://nodejs.org) и [запустить серверный API](../api/README.md) локально, чтобы управлять данными учетной записи. -Вы можете проверить, что сервер работает корректно, выполнив эту команду в терминале: +Вы можете проверить, правильно ли работает сервер, выполнив эту команду в терминале: ```sh curl http://localhost:5000/api @@ -34,32 +34,32 @@ curl http://localhost:5000/api ## Пересмотр управления состоянием -В [предыдущем уроке](../3-data/README.md) мы ввели базовую концепцию состояния в нашем приложении с помощью глобальной переменной `account`, которая содержит банковские данные текущего пользователя. Однако наша текущая реализация имеет несколько недостатков. Попробуйте обновить страницу, находясь на панели управления. Что происходит? +В [предыдущем уроке](../3-data/README.md) мы ввели базовое понятие состояния в нашем приложении с помощью глобальной переменной `account`, которая содержит банковские данные текущего авторизованного пользователя. Однако в текущей реализации есть недостатки. Попробуйте обновить страницу, находясь на панели управления. Что происходит? -Есть три проблемы с текущим кодом: +В текущем коде есть три проблемы: -- Состояние не сохраняется, так как обновление браузера возвращает вас на страницу входа. -- Существует несколько функций, которые изменяют состояние. По мере роста приложения это может затруднить отслеживание изменений, и легко забыть обновить одну из них. -- Состояние не очищается, поэтому при нажатии на *Выход* данные учетной записи остаются, даже если вы находитесь на странице входа. +- Состояние не сохраняется: при обновлении страницы вы возвращаетесь на страницу входа. +- Существует несколько функций, которые изменяют состояние. По мере роста приложения это может затруднить отслеживание изменений, и легко забыть обновить что-то одно. +- Состояние не очищается: когда вы нажимаете *Выйти*, данные учетной записи остаются, даже если вы находитесь на странице входа. Мы могли бы обновить наш код, чтобы решить эти проблемы по отдельности, но это привело бы к дублированию кода и усложнило бы приложение. Или мы могли бы остановиться на несколько минут и пересмотреть нашу стратегию. > Какие проблемы мы действительно пытаемся решить? -[Управление состоянием](https://en.wikipedia.org/wiki/State_management) заключается в поиске хорошего подхода для решения двух конкретных проблем: +[Управление состоянием](https://en.wikipedia.org/wiki/State_management) заключается в поиске подходящего подхода для решения двух основных проблем: - Как сделать потоки данных в приложении понятными? -- Как обеспечить синхронность данных состояния с пользовательским интерфейсом (и наоборот)? +- Как обеспечить синхронизацию данных состояния с пользовательским интерфейсом (и наоборот)? После того как вы решите эти проблемы, любые другие возникающие вопросы либо уже будут решены, либо станут проще для решения. Существует множество подходов к решению этих проблем, но мы выберем распространенное решение, которое заключается в **централизации данных и способов их изменения**. Потоки данных будут выглядеть следующим образом: ![Схема, показывающая потоки данных между HTML, действиями пользователя и состоянием](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.ru.png) -> Мы не будем здесь рассматривать часть, где данные автоматически вызывают обновление представления, так как это связано с более сложными концепциями [реактивного программирования](https://en.wikipedia.org/wiki/Reactive_programming). Это хороший предмет для дальнейшего изучения, если вы готовы к глубокому погружению. +> Здесь мы не будем рассматривать часть, где данные автоматически обновляют представление, так как это связано с более сложными концепциями [реактивного программирования](https://en.wikipedia.org/wiki/Reactive_programming). Это хорошая тема для дальнейшего изучения, если вы хотите углубиться. -✅ Существует множество библиотек с различными подходами к управлению состоянием, [Redux](https://redux.js.org) является популярным вариантом. Ознакомьтесь с концепциями и шаблонами, которые используются, так как это часто помогает понять потенциальные проблемы, с которыми вы можете столкнуться в крупных веб-приложениях, и способы их решения. +✅ Существует множество библиотек с разными подходами к управлению состоянием, [Redux](https://redux.js.org) — один из популярных вариантов. Ознакомьтесь с концепциями и шаблонами, которые используются, так как это часто помогает понять потенциальные проблемы, с которыми вы можете столкнуться в крупных веб-приложениях, и способы их решения. -### Задача +### Задание Начнем с небольшого рефакторинга. Замените объявление `account`: @@ -75,7 +75,7 @@ let state = { }; ``` -Идея заключается в *централизации* всех данных нашего приложения в одном объекте состояния. Пока у нас есть только `account` в состоянии, поэтому это не сильно меняет ситуацию, но создает основу для дальнейших изменений. +Идея состоит в том, чтобы *централизовать* все данные нашего приложения в одном объекте состояния. Пока у нас есть только `account` в состоянии, поэтому это не сильно изменит ситуацию, но создаст основу для дальнейших изменений. Также нужно обновить функции, которые его используют. В функциях `register()` и `login()` замените `account = ...` на `state.account = ...`; @@ -85,21 +85,21 @@ let state = { const account = state.account; ``` -Этот рефакторинг сам по себе не принес больших улучшений, но его идея заключалась в создании основы для следующих изменений. +Сам по себе этот рефакторинг не принес больших улучшений, но его идея — заложить основу для следующих изменений. ## Отслеживание изменений данных Теперь, когда мы создали объект `state` для хранения данных, следующим шагом будет централизация обновлений. Цель — упростить отслеживание любых изменений и времени их возникновения. -Чтобы избежать изменений объекта `state`, также рекомендуется считать его [*неизменяемым*](https://en.wikipedia.org/wiki/Immutable_object), то есть таким, который нельзя модифицировать. Это также означает, что вам нужно создать новый объект состояния, если вы хотите что-то изменить в нем. Таким образом, вы защищаете себя от потенциально нежелательных [побочных эффектов](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) и открываете возможности для новых функций в вашем приложении, таких как реализация отмены/повтора, а также упрощаете отладку. Например, вы можете записывать каждое изменение состояния и сохранять историю изменений, чтобы понять источник ошибки. +Чтобы избежать изменений в объекте `state`, также полезно рассматривать его как [*неизменяемый*](https://en.wikipedia.org/wiki/Immutable_object), то есть такой, который нельзя изменить. Это также означает, что для изменения чего-либо в нем нужно создать новый объект состояния. Такой подход защищает от нежелательных [побочных эффектов](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) и открывает возможности для новых функций в приложении, таких как реализация отмены/повтора действий, а также упрощает отладку. Например, вы могли бы записывать каждое изменение состояния и сохранять историю изменений, чтобы понять источник ошибки. -В JavaScript вы можете использовать [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) для создания неизменяемой версии объекта. Если вы попытаетесь внести изменения в неизменяемый объект, будет вызвано исключение. +В JavaScript можно использовать [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) для создания неизменяемой версии объекта. Если вы попытаетесь внести изменения в неизменяемый объект, будет вызвано исключение. ✅ Знаете ли вы разницу между *поверхностным* и *глубоким* неизменяемым объектом? Вы можете прочитать об этом [здесь](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). -### Задача +### Задание -Создадим новую функцию `updateState()`: +Давайте создадим новую функцию `updateState()`: ```js function updateState(property, newData) { @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -В этой функции мы создаем новый объект состояния и копируем данные из предыдущего состояния, используя [*оператор распространения (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Затем мы переопределяем конкретное свойство объекта состояния новыми данными, используя [нотацию скобок](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` для присваивания. Наконец, мы блокируем объект, чтобы предотвратить модификации, используя `Object.freeze()`. Пока у нас есть только свойство `account`, хранящееся в состоянии, но с этим подходом вы можете добавлять столько свойств, сколько вам нужно. +В этой функции мы создаем новый объект состояния и копируем данные из предыдущего состояния, используя [*оператор распространения (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Затем мы переопределяем конкретное свойство объекта состояния новыми данными, используя [скобочную нотацию](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` для присвоения. Наконец, мы блокируем объект, чтобы предотвратить его изменения, с помощью `Object.freeze()`. Пока у нас есть только свойство `account` в состоянии, но с этим подходом вы можете добавлять столько свойств, сколько нужно. Также обновим инициализацию `state`, чтобы убедиться, что начальное состояние тоже заморожено: @@ -120,7 +120,7 @@ let state = Object.freeze({ }); ``` -После этого обновите функцию `register`, заменив присваивание `state.account = result;` на: +После этого обновите функцию `register`, заменив присвоение `state.account = result;` на: ```js updateState('account', result); @@ -132,7 +132,7 @@ updateState('account', result); updateState('account', data); ``` -Теперь воспользуемся случаем, чтобы исправить проблему, связанную с тем, что данные учетной записи не очищаются, когда пользователь нажимает на *Выход*. +Теперь воспользуемся случаем, чтобы исправить проблему с данными учетной записи, которые не очищаются, когда пользователь нажимает на *Выйти*. Создайте новую функцию `logout()`: @@ -143,35 +143,35 @@ function logout() { } ``` -В `updateDashboard()` замените перенаправление `return navigate('/login');` на `return logout();` +В `updateDashboard()` замените перенаправление `return navigate('/login');` на `return logout();`; -Попробуйте зарегистрировать новую учетную запись, выйти из системы и снова войти, чтобы убедиться, что все работает корректно. +Попробуйте зарегистрировать новую учетную запись, выйти и снова войти, чтобы убедиться, что все работает правильно. -> Совет: вы можете посмотреть все изменения состояния, добавив `console.log(state)` в конце `updateState()` и открыв консоль в инструментах разработчика вашего браузера. +> Совет: вы можете посмотреть все изменения состояния, добавив `console.log(state)` в конец `updateState()` и открыв консоль в инструментах разработчика вашего браузера. ## Сохранение состояния -Большинство веб-приложений нуждаются в сохранении данных для корректной работы. Все критические данные обычно хранятся в базе данных и доступны через серверный API, как, например, данные учетной записи пользователя в нашем случае. Но иногда также полезно сохранять некоторые данные на клиенте, который работает в вашем браузере, для улучшения пользовательского опыта или повышения производительности загрузки. +Большинство веб-приложений нуждаются в сохранении данных для корректной работы. Все критические данные обычно хранятся в базе данных и доступны через серверный API, как в случае с данными учетной записи пользователя. Но иногда также полезно сохранять некоторые данные на клиентском приложении, работающем в вашем браузере, чтобы улучшить пользовательский опыт или повысить производительность загрузки. -Когда вы хотите сохранить данные в браузере, есть несколько важных вопросов, которые следует задать: +Когда вы хотите сохранить данные в браузере, важно задать себе несколько вопросов: -- *Являются ли данные конфиденциальными?* Следует избегать хранения любых конфиденциальных данных на клиенте, таких как пароли пользователей. -- *Как долго вам нужно хранить эти данные?* Планируете ли вы использовать эти данные только в текущем сеансе или хотите, чтобы они хранились навсегда? +- *Являются ли данные конфиденциальными?* Следует избегать хранения конфиденциальных данных на клиенте, таких как пароли пользователей. +- *Как долго вам нужно хранить эти данные?* Планируете ли вы использовать эти данные только в текущей сессии или хотите сохранить их навсегда? -Существует несколько способов хранения информации внутри веб-приложения, в зависимости от того, что вы хотите достичь. Например, вы можете использовать URL-адреса для хранения поискового запроса и сделать его доступным для других пользователей. Вы также можете использовать [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), если данные нужно передавать на сервер, например, информацию для [аутентификации](https://en.wikipedia.org/wiki/Authentication). +Существует несколько способов хранения информации внутри веб-приложения, в зависимости от ваших целей. Например, вы можете использовать URL-адреса для хранения поисковых запросов и сделать их доступными для других пользователей. Вы также можете использовать [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), если данные нужно передавать на сервер, например, для [аутентификации](https://en.wikipedia.org/wiki/Authentication). -Другой вариант — использовать один из многих API браузера для хранения данных. Два из них особенно интересны: +Еще один вариант — использовать один из многих API браузера для хранения данных. Два из них особенно интересны: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [хранилище ключ/значение](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), позволяющее сохранять данные, специфичные для текущего веб-сайта, между различными сеансами. Сохраненные данные никогда не истекают. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): работает так же, как `localStorage`, за исключением того, что данные, хранящиеся в нем, очищаются при завершении сеанса (при закрытии браузера). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [хранилище ключ/значение](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), позволяющее сохранять данные, специфичные для текущего веб-сайта, между сессиями. Сохраненные данные никогда не истекают. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): работает так же, как `localStorage`, за исключением того, что данные очищаются, когда сессия завершается (при закрытии браузера). -Обратите внимание, что оба этих API позволяют хранить только [строки](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Если вы хотите хранить сложные объекты, вам нужно сериализовать их в формате [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) с помощью [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Обратите внимание, что оба этих API позволяют хранить только [строки](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Если вы хотите сохранить сложные объекты, вам нужно сериализовать их в формате [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) с помощью [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Если вы хотите создать веб-приложение, которое не работает с сервером, также можно создать базу данных на клиенте, используя API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Этот вариант предназначен для сложных случаев использования или если вам нужно хранить значительное количество данных, так как он более сложен в использовании. +✅ Если вы хотите создать веб-приложение, которое работает без сервера, также можно создать базу данных на клиенте, используя API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Этот вариант подходит для сложных случаев или если вам нужно хранить значительное количество данных, так как он более сложен в использовании. -### Задача +### Задание -Мы хотим, чтобы наши пользователи оставались в системе, пока они явно не нажмут кнопку *Выход*, поэтому будем использовать `localStorage` для хранения данных учетной записи. Сначала определим ключ, который будем использовать для хранения данных. +Мы хотим, чтобы наши пользователи оставались авторизованными, пока они явно не нажмут кнопку *Выйти*, поэтому будем использовать `localStorage` для хранения данных учетной записи. Сначала определим ключ, который будем использовать для хранения данных. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -С этим данные учетной записи пользователя будут сохраняться и всегда актуальны, так как мы централизовали все обновления состояния. Здесь мы начинаем получать выгоду от всех предыдущих рефакторингов 🙂. +С этим пользовательские данные учетной записи будут сохраняться и всегда актуальны, так как мы централизовали все обновления состояния. Именно здесь мы начинаем получать выгоду от всех предыдущих рефакторингов 🙂. -Так как данные сохраняются, также нужно позаботиться об их восстановлении при загрузке приложения. Поскольку у нас начинает появляться больше кода для инициализации, может быть хорошей идеей создать новую функцию `init`, которая также включает наш предыдущий код внизу `app.js`: +Поскольку данные сохраняются, также нужно позаботиться об их восстановлении при загрузке приложения. Поскольку у нас начнет появляться больше кода инициализации, возможно, стоит создать новую функцию `init`, которая также включает наш предыдущий код в конце `app.js`: ```js function init() { @@ -202,15 +202,15 @@ function init() { init(); ``` -Здесь мы восстанавливаем сохраненные данные, и если они есть, обновляем состояние соответствующим образом. Важно сделать это *до* обновления маршрута, так как может быть код, который зависит от состояния во время обновления страницы. +Здесь мы извлекаем сохраненные данные, и если они есть, обновляем состояние соответствующим образом. Важно сделать это *до* обновления маршрута, так как может быть код, зависящий от состояния во время обновления страницы. -Мы также можем сделать страницу *Панель управления* страницей по умолчанию для нашего приложения, так как теперь мы сохраняем данные учетной записи. Если данные не найдены, панель управления все равно перенаправляет на страницу *Вход*. В `updateRoute()` замените резервный вариант `return navigate('/login');` на `return navigate('/dashboard');`. +Мы также можем сделать страницу *Dashboard* страницей по умолчанию для нашего приложения, так как теперь мы сохраняем данные учетной записи. Если данные не найдены, панель управления сама перенаправляет на страницу *Login*. В `updateRoute()` замените резервное значение `return navigate('/login');` на `return navigate('/dashboard');`. -Теперь войдите в приложение и попробуйте обновить страницу. Вы должны остаться на панели управления. С этим обновлением мы решили все наши первоначальные проблемы... +Теперь войдите в приложение и попробуйте обновить страницу. Вы должны остаться на панели управления. С этим обновлением мы решили все наши начальные проблемы... ## Обновление данных -...Но мы могли также создать новую проблему. Упс! +...Но мы могли также создать новую проблему. Ой! Перейдите на панель управления, используя учетную запись `test`, затем выполните эту команду в терминале, чтобы создать новую транзакцию: @@ -223,11 +223,11 @@ curl --request POST \ Теперь попробуйте обновить страницу панели управления в браузере. Что происходит? Видите ли вы новую транзакцию? -Состояние сохраняется бесконечно благодаря `localStorage`, но это также означает, что оно никогда не обновляется, пока вы не выйдете из приложения и снова войдете! +Состояние сохраняется на неопределенный срок благодаря `localStorage`, но это также означает, что оно никогда не обновляется, пока вы не выйдете из приложения и снова не войдете! -Один из возможных способов решения этой проблемы — перезагружать данные учетной записи каждый раз, когда загружается панель управления, чтобы избежать устаревших данных. +Одна из возможных стратегий решения этой проблемы — перезагружать данные учетной записи каждый раз, когда загружается панель управления, чтобы избежать устаревших данных. -### Задача +### Задание Создайте новую функцию `updateAccountData`: @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Этот метод проверяет, что пользователь вошел в систему, а затем перезагружает данные учетной записи с сервера. +Этот метод проверяет, что пользователь авторизован, а затем перезагружает данные учетной записи с сервера. Создайте еще одну функцию с именем `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Эта функция обновляет данные учетной записи, а затем обновляет HTML страницы панели управления. Это то, что нужно вызывать при загрузке маршрута панели управления. Обновите определение маршрута: +Эта функция обновляет данные учетной записи, а затем обновляет HTML панели управления. Именно ее нужно вызывать, когда загружается маршрут панели управления. Обновите определение маршрута: ```js const routes = { @@ -273,16 +273,16 @@ const routes = { ## 🚀 Задание -Теперь, когда мы перезагружаем данные учетной записи каждый раз, когда загружается панель управления, как вы думаете, нужно ли нам сохранять *все данные учетной записи*? +Теперь, когда мы перезагружаем данные учетной записи каждый раз, когда загружается панель управления, как вы думаете, нужно ли нам по-прежнему сохранять *все данные учетной записи*? -Попробуйте вместе изменить то, что сохраняется и загружается из `localStorage`, чтобы включать только то, что абсолютно необходимо для работы приложения. +Попробуйте вместе изменить то, что сохраняется и загружается из `localStorage`, чтобы включить только то, что абсолютно необходимо для работы приложения. -## Итоговый тест - -[Итоговый тест](https://ff-quizzes.netlify.app/web/quiz/48) +## Тест после лекции +[Тест после лекции](https://ff-quizzes.netlify.app/web/quiz/48) ## Задание -[Реализация диалога "Добавить транзакцию"](assignment.md) + +[Реализовать диалог "Добавить транзакцию"](assignment.md) Вот пример результата после выполнения задания: @@ -291,4 +291,4 @@ const routes = { --- **Отказ от ответственности**: -Этот документ был переведен с использованием сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Хотя мы стремимся к точности, пожалуйста, учитывайте, что автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его родном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода. \ No newline at end of file +Этот документ был переведен с помощью сервиса автоматического перевода [Co-op Translator](https://github.com/Azure/co-op-translator). Несмотря на наши усилия обеспечить точность перевода, автоматические переводы могут содержать ошибки или неточности. Оригинальный документ на его родном языке следует считать авторитетным источником. Для получения критически важной информации рекомендуется профессиональный перевод человеком. Мы не несем ответственности за любые недоразумения или неправильные интерпретации, возникшие в результате использования данного перевода. \ No newline at end of file diff --git a/translations/sk/7-bank-project/4-state-management/README.md b/translations/sk/7-bank-project/4-state-management/README.md index a4fcc15c6..3ceaa36ee 100644 --- a/translations/sk/7-bank-project/4-state-management/README.md +++ b/translations/sk/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Izdelava bančne aplikacije, 4. del: Koncepti upravljanja stanja +# Ustvarjanje bančne aplikacije, 4. del: Koncepti upravljanja stanja ## Predhodni kviz @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Uvod -Ko spletna aplikacija raste, postane težko slediti vsem tokovom podatkov. Kateri del kode pridobi podatke, katera stran jih uporablja, kje in kdaj jih je treba posodobiti... hitro se lahko znajdemo v zmešnjavi kode, ki jo je težko vzdrževati. To je še posebej res, ko je treba podatke deliti med različnimi stranmi aplikacije, na primer podatke o uporabniku. Koncept *upravljanja stanja* je vedno obstajal v vseh vrstah programov, vendar je zaradi naraščajoče kompleksnosti spletnih aplikacij postal ključna točka pri razvoju. +Ko spletna aplikacija raste, postane težko slediti vsem tokovom podatkov. Kateri del kode pridobi podatke, katera stran jih uporablja, kje in kdaj jih je treba posodobiti... hitro se lahko znajdemo z zmedeno kodo, ki jo je težko vzdrževati. To je še posebej res, ko je treba podatke deliti med različnimi stranmi aplikacije, na primer podatke o uporabniku. Koncept *upravljanja stanja* je vedno obstajal v vseh vrstah programov, vendar je zaradi naraščajoče kompleksnosti spletnih aplikacij zdaj ključna točka, o kateri je treba razmišljati med razvojem. -V tem zadnjem delu bomo pregledali aplikacijo, ki smo jo zgradili, da ponovno premislimo, kako je stanje upravljano, kar bo omogočilo podporo osvežitvi brskalnika kadarkoli in ohranjanje podatkov med uporabniškimi sejami. +V tem zadnjem delu bomo pregledali aplikacijo, ki smo jo zgradili, da ponovno premislimo, kako je stanje upravljano, kar omogoča podporo osvežitvi brskalnika kadarkoli in ohranjanje podatkov med uporabniškimi sejami. ### Predpogoji -Za to lekcijo morate dokončati [pridobivanje podatkov](../3-data/README.md) v spletni aplikaciji. Prav tako morate namestiti [Node.js](https://nodejs.org) in [zagnati strežniški API](../api/README.md) lokalno, da lahko upravljate podatke o računih. +Za to lekcijo morate dokončati [pridobivanje podatkov](../3-data/README.md) v aplikaciji. Prav tako morate namestiti [Node.js](https://nodejs.org) in [zagnati strežniški API](../api/README.md) lokalno, da lahko upravljate podatke o računih. Preverite, ali strežnik pravilno deluje, tako da v terminalu zaženete naslednji ukaz: @@ -34,28 +34,28 @@ curl http://localhost:5000/api ## Ponovno premislimo upravljanje stanja -V [prejšnji lekciji](../3-data/README.md) smo v aplikaciji predstavili osnovni koncept stanja z globalno spremenljivko `account`, ki vsebuje bančne podatke trenutno prijavljenega uporabnika. Vendar ima naša trenutna implementacija nekaj pomanjkljivosti. Poskusite osvežiti stran, ko ste na nadzorni plošči. Kaj se zgodi? +V [prejšnji lekciji](../3-data/README.md) smo predstavili osnovni koncept stanja v naši aplikaciji z globalno spremenljivko `account`, ki vsebuje bančne podatke trenutno prijavljenega uporabnika. Vendar ima naša trenutna implementacija nekaj pomanjkljivosti. Poskusite osvežiti stran, ko ste na nadzorni plošči. Kaj se zgodi? Trenutna koda ima tri težave: - Stanje ni ohranjeno, saj vas osvežitev brskalnika vrne na stran za prijavo. -- Obstaja več funkcij, ki spreminjajo stanje. Ko aplikacija raste, postane težko slediti spremembam in zlahka pozabimo posodobiti eno od njih. +- Obstaja več funkcij, ki spreminjajo stanje. Ko aplikacija raste, to lahko oteži sledenje spremembam in zlahka pozabimo posodobiti eno od njih. - Stanje ni očiščeno, zato so podatki o računu še vedno prisotni, ko kliknete *Odjava*, čeprav ste na strani za prijavo. -Te težave bi lahko reševali eno za drugo, vendar bi to ustvarilo več podvajanja kode in aplikacijo naredilo bolj zapleteno ter težje vzdrževano. Ali pa bi si lahko vzeli nekaj minut in premislili našo strategijo. +Lahko bi posodobili našo kodo, da bi te težave reševali eno za drugo, vendar bi to ustvarilo več podvajanja kode in naredilo aplikacijo bolj zapleteno ter težje vzdrževano. Ali pa bi si lahko vzeli nekaj minut in premislili našo strategijo. -> Katere težave pravzaprav poskušamo rešiti? +> Katere težave pravzaprav poskušamo rešiti tukaj? [Upravljanje stanja](https://en.wikipedia.org/wiki/State_management) se osredotoča na iskanje dobrega pristopa za reševanje teh dveh specifičnih težav: - Kako ohraniti tokove podatkov v aplikaciji razumljive? -- Kako zagotoviti, da so podatki stanja vedno usklajeni z uporabniškim vmesnikom (in obratno)? +- Kako ohraniti podatke o stanju vedno usklajene z uporabniškim vmesnikom (in obratno)? -Ko se lotite teh težav, so lahko druge težave že rešene ali pa jih je lažje odpraviti. Obstaja veliko možnih pristopov za reševanje teh težav, vendar bomo uporabili običajno rešitev, ki vključuje **centralizacijo podatkov in načinov za njihovo spreminjanje**. Tokovi podatkov bi potekali takole: +Ko se lotite teh težav, so lahko vse druge težave, ki jih imate, že rešene ali pa jih je lažje rešiti. Obstaja veliko možnih pristopov za reševanje teh težav, vendar bomo uporabili običajno rešitev, ki vključuje **centralizacijo podatkov in načinov za njihovo spreminjanje**. Tokovi podatkov bi potekali takole: ![Shema, ki prikazuje tokove podatkov med HTML-jem, uporabniškimi dejanji in stanjem](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.sl.png) -> Tukaj ne bomo obravnavali dela, kjer podatki samodejno sprožijo posodobitev pogleda, saj je povezan z naprednejšimi koncepti [reaktivnega programiranja](https://en.wikipedia.org/wiki/Reactive_programming). To je dobra tema za nadaljnje poglobljeno raziskovanje. +> Tukaj ne bomo obravnavali dela, kjer podatki samodejno sprožijo posodobitev pogleda, saj je to povezano z naprednejšimi koncepti [reaktivnega programiranja](https://en.wikipedia.org/wiki/Reactive_programming). To je dobra tema za nadaljnje poglobljeno raziskovanje. ✅ Obstaja veliko knjižnic z različnimi pristopi k upravljanju stanja, [Redux](https://redux.js.org) pa je priljubljena izbira. Oglejte si koncepte in vzorce, ki jih uporablja, saj je to pogosto dober način za učenje o potencialnih težavah, s katerimi se lahko soočate v velikih spletnih aplikacijah, in kako jih je mogoče rešiti. @@ -75,9 +75,9 @@ let state = { }; ``` -Ideja je, da *centraliziramo* vse podatke aplikacije v enem samem objektu stanja. Trenutno imamo v stanju samo `account`, zato se ne spremeni veliko, vendar to odpira pot za nadaljnje izboljšave. +Ideja je, da *centraliziramo* vse podatke naše aplikacije v enem samem objektu stanja. Trenutno imamo v stanju samo `account`, zato se ne spremeni veliko, vendar ustvarja pot za prihodnje nadgradnje. -Posodobiti moramo tudi funkcije, ki ga uporabljajo. V funkcijah `register()` in `login()` zamenjajte `account = ...` z `state.account = ...`; +Prav tako moramo posodobiti funkcije, ki ga uporabljajo. V funkcijah `register()` in `login()` zamenjajte `account = ...` z `state.account = ...`; Na vrhu funkcije `updateDashboard()` dodajte to vrstico: @@ -91,11 +91,11 @@ To prestrukturiranje samo po sebi ni prineslo veliko izboljšav, vendar je ideja Zdaj, ko smo vzpostavili objekt `state` za shranjevanje naših podatkov, je naslednji korak centralizacija posodobitev. Cilj je olajšati sledenje vsem spremembam in kdaj se zgodijo. -Da bi se izognili spremembam objekta `state`, je dobra praksa, da ga obravnavamo kot [*nepremičnega*](https://en.wikipedia.org/wiki/Immutable_object), kar pomeni, da ga ni mogoče spreminjati. To pomeni, da morate ustvariti nov objekt stanja, če želite kaj spremeniti v njem. S tem se zaščitite pred morebitnimi neželenimi [stranskimi učinki](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) in odprete možnosti za nove funkcije v aplikaciji, kot je implementacija razveljavitve/ponovne uveljavitve, hkrati pa olajšate odpravljanje napak. Na primer, lahko beležite vsako spremembo stanja in hranite zgodovino sprememb, da razumete vir napake. +Da bi se izognili spremembam objekta `state`, je dobra praksa, da ga obravnavamo kot [*nepremičnega*](https://en.wikipedia.org/wiki/Immutable_object), kar pomeni, da ga sploh ni mogoče spreminjati. To pomeni, da morate ustvariti nov objekt stanja, če želite karkoli spremeniti v njem. S tem se zaščitite pred morebitnimi neželenimi [stranskimi učinki](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) in odprete možnosti za nove funkcije v vaši aplikaciji, kot je implementacija razveljavitve/ponovne uveljavitve, hkrati pa olajšate odpravljanje napak. Na primer, lahko beležite vsako spremembo stanja in hranite zgodovino sprememb, da razumete vir napake. -V JavaScriptu lahko uporabite [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) za ustvarjanje nepremičnega objekta. Če poskušate narediti spremembe na nepremičnem objektu, bo sprožena izjema. +V JavaScriptu lahko uporabite [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) za ustvarjanje nepremičnega objekta. Če poskušate narediti spremembe nepremičnemu objektu, bo sprožena izjema. -✅ Ali poznate razliko med *plitkim* in *globokim* nepremičnim objektom? Preberite več o tem [tukaj](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Ali poznate razliko med *plitkim* in *globokim* nepremičnim objektom? Preberite o tem [tukaj](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Naloga @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -V tej funkciji ustvarimo nov objekt stanja in kopiramo podatke iz prejšnjega stanja z uporabo [*operatorja razširitve (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Nato preglasimo določeno lastnost objekta stanja z novimi podatki z uporabo [notacije z oglatimi oklepaji](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` za dodelitev. Na koncu zaklenemo objekt, da preprečimo spremembe z uporabo `Object.freeze()`. Trenutno imamo v stanju shranjeno samo lastnost `account`, vendar lahko s tem pristopom dodate toliko lastnosti, kot jih potrebujete. +V tej funkciji ustvarjamo nov objekt stanja in kopiramo podatke iz prejšnjega stanja z uporabo [*operatorja razširitve (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Nato preglasimo določeno lastnost objekta stanja z novimi podatki z uporabo [notacije z oglatimi oklepaji](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` za dodelitev. Na koncu zaklenemo objekt, da preprečimo spremembe z `Object.freeze()`. Trenutno imamo v stanju shranjeno samo lastnost `account`, vendar lahko s tem pristopom dodate toliko lastnosti, kot jih potrebujete. -Posodobili bomo tudi inicializacijo `state`, da zagotovimo, da je začetno stanje prav tako zamrznjeno: +Prav tako bomo posodobili inicializacijo `state`, da zagotovimo, da je začetno stanje tudi zamrznjeno: ```js let state = Object.freeze({ @@ -145,20 +145,20 @@ function logout() { V `updateDashboard()` zamenjajte preusmeritev `return navigate('/login');` z `return logout();`; -Poskusite registrirati nov račun, se odjaviti in ponovno prijaviti, da preverite, ali vse še vedno deluje pravilno. +Poskusite registrirati nov račun, se odjaviti in se ponovno prijaviti, da preverite, ali vse še vedno deluje pravilno. -> Nasvet: lahko si ogledate vse spremembe stanja tako, da dodate `console.log(state)` na dnu funkcije `updateState()` in odprete konzolo v orodjih za razvijalce vašega brskalnika. +> Nasvet: lahko si ogledate vse spremembe stanja tako, da dodate `console.log(state)` na dnu `updateState()` in odprete konzolo v orodjih za razvijalce vašega brskalnika. ## Ohranjanje stanja -Večina spletnih aplikacij mora ohranjati podatke, da lahko pravilno deluje. Vsi ključni podatki so običajno shranjeni v podatkovni bazi in dostopni prek strežniškega API-ja, kot so podatki o uporabniških računih v našem primeru. Včasih pa je zanimivo ohraniti nekatere podatke v odjemalski aplikaciji, ki se izvaja v vašem brskalniku, za boljšo uporabniško izkušnjo ali izboljšanje zmogljivosti nalaganja. +Večina spletnih aplikacij mora ohraniti podatke, da lahko pravilno deluje. Vsi ključni podatki so običajno shranjeni v bazi podatkov in dostopni prek strežniškega API-ja, kot so podatki o uporabniških računih v našem primeru. Včasih pa je zanimivo ohraniti nekatere podatke v odjemalski aplikaciji, ki se izvaja v vašem brskalniku, za boljšo uporabniško izkušnjo ali za izboljšanje zmogljivosti nalaganja. Ko želite ohraniti podatke v brskalniku, si morate zastaviti nekaj pomembnih vprašanj: - *Ali so podatki občutljivi?* Izogibajte se shranjevanju občutljivih podatkov na odjemalcu, kot so gesla uporabnikov. - *Kako dolgo potrebujete te podatke?* Ali nameravate dostopati do teh podatkov samo med trenutno sejo ali jih želite shraniti za vedno? -Obstaja več načinov za shranjevanje informacij znotraj spletne aplikacije, odvisno od tega, kaj želite doseči. Na primer, lahko uporabite URL-je za shranjevanje iskalne poizvedbe in jo naredite deljivo med uporabniki. Lahko uporabite tudi [HTTP piškotke](https://developer.mozilla.org/docs/Web/HTTP/Cookies), če je treba podatke deliti s strežnikom, na primer informacije o [avtentikaciji](https://en.wikipedia.org/wiki/Authentication). +Obstaja več načinov za shranjevanje informacij znotraj spletne aplikacije, odvisno od tega, kaj želite doseči. Na primer, lahko uporabite URL-je za shranjevanje iskalne poizvedbe in jo naredite deljivo med uporabniki. Prav tako lahko uporabite [HTTP piškotke](https://developer.mozilla.org/docs/Web/HTTP/Cookies), če je treba podatke deliti s strežnikom, kot so informacije o [avtentikaciji](https://en.wikipedia.org/wiki/Authentication). Druga možnost je uporaba ene od številnih API-jev brskalnika za shranjevanje podatkov. Dva od njih sta še posebej zanimiva: @@ -167,11 +167,11 @@ Druga možnost je uporaba ene od številnih API-jev brskalnika za shranjevanje p Upoštevajte, da oba API-ja omogočata shranjevanje samo [nizov](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Če želite shraniti kompleksne objekte, jih boste morali serializirati v format [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) z uporabo [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Če želite ustvariti spletno aplikacijo, ki ne deluje s strežnikom, je mogoče ustvariti podatkovno bazo na odjemalcu z uporabo API-ja [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ta je rezerviran za napredne primere uporabe ali če morate shraniti večjo količino podatkov, saj je bolj zapleten za uporabo. +✅ Če želite ustvariti spletno aplikacijo, ki ne deluje s strežnikom, je mogoče ustvariti bazo podatkov na odjemalcu z uporabo API-ja [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ta je rezerviran za napredne primere uporabe ali če morate shraniti večjo količino podatkov, saj je bolj zapleten za uporabo. ### Naloga -Želimo, da naši uporabniki ostanejo prijavljeni, dokler izrecno ne kliknejo gumba *Odjava*, zato bomo uporabili `localStorage` za shranjevanje podatkov o računu. Najprej definirajmo ključ, ki ga bomo uporabili za shranjevanje naših podatkov. +Želimo, da naši uporabniki ostanejo prijavljeni, dokler izrecno ne kliknejo na gumb *Odjava*, zato bomo uporabili `localStorage` za shranjevanje podatkov o računu. Najprej definirajmo ključ, ki ga bomo uporabili za shranjevanje naših podatkov. ```js const storageKey = 'savedAccount'; @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); S tem bodo podatki o uporabniškem računu ohranjeni in vedno posodobljeni, saj smo prej centralizirali vse posodobitve stanja. Tukaj začnemo izkoriščati vse naše prejšnje prestrukturiranje 🙂. -Ker so podatki shranjeni, moramo poskrbeti tudi za njihovo obnovitev, ko se aplikacija naloži. Ker bomo začeli imeti več inicializacijske kode, je morda dobra ideja, da ustvarimo novo funkcijo `init`, ki vključuje tudi našo prejšnjo kodo na dnu `app.js`: +Ker so podatki shranjeni, moramo poskrbeti tudi za njihovo obnovitev, ko se aplikacija naloži. Ker bomo začeli imeti več inicializacijske kode, je morda dobra ideja ustvariti novo funkcijo `init`, ki vključuje tudi našo prejšnjo kodo na dnu `app.js`: ```js function init() { @@ -204,15 +204,15 @@ init(); Tukaj pridobimo shranjene podatke, in če obstajajo, ustrezno posodobimo stanje. Pomembno je, da to storimo *pred* posodobitvijo poti, saj lahko obstaja koda, ki se zanaša na stanje med posodobitvijo strani. -Privzeto stran naše aplikacije lahko naredimo *Nadzorno ploščo*, saj zdaj ohranjamo podatke o računu. Če podatki niso najdeni, nadzorna plošča poskrbi za preusmeritev na stran *Prijava*. V `updateRoute()` zamenjajte privzeto `return navigate('/login');` z `return navigate('/dashboard');`. +Prav tako lahko naredimo stran *Nadzorna plošča* privzeto stran naše aplikacije, saj zdaj ohranjamo podatke o računu. Če podatki niso najdeni, nadzorna plošča poskrbi za preusmeritev na stran *Prijava*. V `updateRoute()` zamenjajte privzeto `return navigate('/login');` z `return navigate('/dashboard');`. -Zdaj se prijavite v aplikacijo in poskusite osvežiti stran. Ostati bi morali na nadzorni plošči. S to posodobitvijo smo odpravili vse naše začetne težave... +Zdaj se prijavite v aplikacijo in poskusite osvežiti stran. Ostati bi morali na nadzorni plošči. S to posodobitvijo smo rešili vse naše začetne težave... ## Osvežitev podatkov ...Ampak morda smo ustvarili novo težavo. Ups! -Pojdite na nadzorno ploščo z računom `test`, nato zaženite ta ukaz v terminalu za ustvarjanje nove transakcije: +Pojdite na nadzorno ploščo z računom `test`, nato zaženite ta ukaz v terminalu, da ustvarite novo transakcijo: ```sh curl --request POST \ @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Zdaj poskusite osvežiti stran nadzorne plošče v brskalniku. Kaj se zgodi? Ali vidite novo transakcijo? +Poskusite osvežiti stran nadzorne plošče v brskalniku zdaj. Kaj se zgodi? Ali vidite novo transakcijo? -Stanje je ohranjeno za nedoločen čas zahvaljujoč `localStorage`, vendar to pomeni, da se nikoli ne posodobi, dokler se ne odjavite iz aplikacije in ponovno prijavite! +Stanje je ohranjeno za nedoločen čas zahvaljujoč `localStorage`, vendar to pomeni, da se nikoli ne posodobi, dokler se ne odjavite iz aplikacije in se ponovno prijavite! -Ena od možnih strategij za odpravo te težave je, da vsakič, ko se naloži nadzorna plošča, ponovno naložimo podatke o računu, da se izognemo zastarelim podatkom. +Ena možna strategija za odpravo tega je, da ponovno naložimo podatke o računu vsakič, ko se naloži nadzorna plošča, da se izognemo zastarelim podatkom. ### Naloga @@ -247,7 +247,7 @@ async function updateAccountData() { } ``` -Ta metoda preveri, ali smo trenutno prijavljeni, nato pa ponovno naloži podatke o računu s strežnika. +Ta metoda preveri, ali smo trenutno prijavljeni, nato ponovno naloži podatke o računu s strežnika. Ustvarite drugo funkcijo z imenom `refresh`: @@ -258,7 +258,7 @@ async function refresh() { } ``` -Ta funkcija posodobi podatke o računu, nato pa poskrbi za posodobitev HTML-ja na strani nadzorne plošče. To je tisto, kar moramo poklicati, ko se naloži pot nadzorne plošče. Posodobite definicijo poti z: +Ta funkcija posodobi podatke o računu, nato poskrbi za posodobitev HTML-ja na strani nadzorne plošče. To je tisto, kar moramo poklicati, ko se naloži pot nadzorne plošče. Posodobite definicijo poti z: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -Zdaj poskusite osvežiti nadzorno ploščo, prikazati bi morali posodobljene podatke o računu. +Poskusite ponovno naložiti nadzorno ploščo zdaj, prikazati bi morali posodobljene podatke o računu. --- ## 🚀 Izziv -Zdaj, ko vsakič, ko se naloži nadzorna plošča, ponovno naložimo podatke o računu, ali menite, da moramo še vedno ohranjati *vse podatke o računu*? +Zdaj, ko ponovno nalagamo podatke o računu vsakič, ko se naloži nadzorna plošča, ali menite, da še vedno potrebujemo ohranjanje *vseh podatkov o računu*? Poskusite skupaj spremeniti, kaj je shranjeno in naloženo iz `localStorage`, da vključuje samo tisto, kar je absolutno potrebno za delovanje aplikacije. ## Zaključni kviz - -[Zaključni kviz](https://ff-quizzes.netlify.app/web/quiz/48) +[Kvizi po predavanju](https://ff-quizzes.netlify.app/web/quiz/48) ## Naloga -[Izvedi "Dodaj transakcijo" pogovorno okno](assignment.md) -Tukaj je primer rezultata po zaključku naloge: +[Implementirajte dialog "Dodaj transakcijo"](assignment.md) + +Tukaj je primer rezultata po zaključeni nalogi: -![Posnetek zaslona, ki prikazuje primer pogovornega okna "Dodaj transakcijo"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sl.png) +![Posnetek zaslona, ki prikazuje primer dialoga "Dodaj transakcijo"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sl.png) --- **Omejitev odgovornosti**: -Ta dokument je bil preveden z uporabo storitve za prevajanje z umetno inteligenco [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem maternem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo profesionalni človeški prevod. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki bi nastale zaradi uporabe tega prevoda. \ No newline at end of file +Ta dokument je bil preveden z uporabo storitve AI za prevajanje [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem maternem jeziku je treba obravnavati kot avtoritativni vir. Za ključne informacije priporočamo profesionalni človeški prevod. Ne prevzemamo odgovornosti za morebitna nesporazumevanja ali napačne razlage, ki izhajajo iz uporabe tega prevoda. \ No newline at end of file diff --git a/translations/sr/7-bank-project/4-state-management/README.md b/translations/sr/7-bank-project/4-state-management/README.md index 97193fd4a..75069e375 100644 --- a/translations/sr/7-bank-project/4-state-management/README.md +++ b/translations/sr/7-bank-project/4-state-management/README.md @@ -1,13 +1,13 @@ -# Изградња банкарске апликације, део 4: Концепти управљања стањем +# Изградња апликације за банкарство, део 4: Концепти управљања стањем ## Квиз пре предавања @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Увод -Како веб апликација расте, постаје изазов пратити све токове података. Који код добија податке, која страница их користи, где и када треба да се ажурирају... лако је завршити са неуредним кодом који је тешко одржавати. Ово је посебно тачно када треба да делите податке између различитих страница ваше апликације, на пример корисничке податке. Концепт *управљања стањем* одувек је постојао у свим врстама програма, али како веб апликације постају све сложеније, сада је то кључна тачка о којој треба размишљати током развоја. +Како веб апликација расте, постаје изазовно пратити све токове података. Који код добија податке, која страница их користи, где и када треба да се ажурирају... лако је завршити са неуредним кодом који је тешко одржавати. Ово је посебно тачно када треба да делите податке између различитих страница апликације, на пример корисничке податке. Концепт *управљања стањем* увек је постојао у свим врстама програма, али како веб апликације постају све сложеније, сада је то кључна тачка о којој треба размишљати током развоја. -У овом завршном делу, прегледаћемо апликацију коју смо изградили како бисмо преиспитали како се стање управља, омогућавајући подршку за освежавање прегледача у било ком тренутку и чување података током корисничких сесија. +У овом завршном делу, размотрићемо апликацију коју смо изградили како бисмо преиспитали начин управљања стањем, омогућавајући подршку за освежавање прегледача у било ком тренутку и чување података током корисничких сесија. ### Предуслови -Потребно је да сте завршили [добијање података](../3-data/README.md) део веб апликације за ову лекцију. Такође треба да инсталирате [Node.js](https://nodejs.org) и [покренете сервер API](../api/README.md) локално како бисте могли да управљате подацима о налогу. +Потребно је да сте завршили [преузимање података](../3-data/README.md) у претходном делу веб апликације за ову лекцију. Такође треба да инсталирате [Node.js](https://nodejs.org) и [покренете сервер API](../api/README.md) локално како бисте могли да управљате подацима о налогу. Можете тестирати да ли сервер ради исправно извршавањем ове команде у терминалу: @@ -34,30 +34,30 @@ curl http://localhost:5000/api ## Преиспитивање управљања стањем -У [претходној лекцији](../3-data/README.md), увели смо основни концепт стања у нашој апликацији са глобалном променљивом `account` која садржи банкарске податке за тренутно пријављеног корисника. Међутим, наша тренутна имплементација има неке недостатке. Покушајте да освежите страницу када сте на контролној табли. Шта се дешава? +У [претходној лекцији](../3-data/README.md), увели смо основни концепт стања у нашој апликацији са глобалном променљивом `account` која садржи банкарске податке за тренутно пријављеног корисника. Међутим, наша тренутна имплементација има неке недостатке. Покушајте да освежите страницу док сте на контролној табли. Шта се дешава? Постоје три проблема са тренутним кодом: - Стање није сачувано, јер освежавање прегледача враћа вас на страницу за пријаву. -- Постоји више функција које мењају стање. Како апликација расте, то може отежати праћење промена и лако је заборавити да се нешто ажурира. -- Стање се не чисти, тако да када кликнете на *Одјава*, подаци о налогу и даље постоје иако сте на страници за пријаву. +- Постоји више функција које мењају стање. Како апликација расте, то може отежати праћење промена и лако је заборавити да ажурирате једну. +- Стање се не чисти, па када кликнете на *Одјави се*, подаци о налогу и даље остају, иако сте на страници за пријаву. -Могли бисмо ажурирати наш код како бисмо решили ове проблеме један по један, али то би створило више дуплирања кода и учинило апликацију сложенијом и тежом за одржавање. Или бисмо могли да застанемо на неколико минута и преиспитамо нашу стратегију. +Могли бисмо ажурирати наш код да решимо ове проблеме један по један, али то би створило више дуплирања кода и учинило апликацију сложенијом и тежом за одржавање. Или бисмо могли да паузирамо на неколико минута и преиспитамо нашу стратегију. -> Које проблеме заправо покушавамо да решимо овде? +> Које проблеме заиста покушавамо да решимо овде? [Управљање стањем](https://en.wikipedia.org/wiki/State_management) се односи на проналажење доброг приступа за решавање ова два конкретна проблема: -- Како одржати токове података у апликацији разумљивим? +- Како учинити токове података у апликацији разумљивим? - Како одржати податке о стању увек синхронизованим са корисничким интерфејсом (и обрнуто)? -Када се позабавите овим питањима, сви други проблеми које можда имате или ће већ бити решени или ће постати лакши за решавање. Постоји много могућих приступа за решавање ових проблема, али ми ћемо се определити за уобичајено решење које се састоји од **централизовања података и начина њиховог мењања**. Токови података би изгледали овако: +Када се позабавите овим питањима, било који други проблеми које можда имате могу бити већ решени или постати лакши за решавање. Постоји много могућих приступа за решавање ових проблема, али ми ћемо се определити за уобичајено решење које се састоји од **централизовања података и начина њиховог мењања**. Токови података би изгледали овако: ![Шема која приказује токове података између HTML-а, корисничких акција и стања](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.sr.png) > Овде нећемо покривати део где подаци аутоматски покрећу ажурирање приказа, јер је то повезано са напреднијим концептима [реактивног програмирања](https://en.wikipedia.org/wiki/Reactive_programming). То је добра тема за дубље истраживање ако сте заинтересовани. -✅ Постоји много библиотека са различитим приступима управљању стањем, [Redux](https://redux.js.org) је популарна опција. Погледајте концепте и обрасце који се користе јер је то често добар начин да научите са којим потенцијалним проблемима се можете суочити у великим веб апликацијама и како их можете решити. +✅ Постоји много библиотека са различитим приступима управљању стањем, [Redux](https://redux.js.org) је популарна опција. Погледајте концепте и обрасце који се користе, јер је то често добар начин да научите о потенцијалним проблемима са којима се можете суочити у великим веб апликацијама и како их можете решити. ### Задатак @@ -75,7 +75,7 @@ let state = { }; ``` -Идеја је да се *централизују* сви подаци апликације у један објекат стања. Тренутно имамо само `account` у стању, тако да се много тога не мења, али ово ствара пут за будуће еволуције. +Идеја је да *централизујемо* све податке наше апликације у један објекат стања. Тренутно имамо само `account` у стању, тако да се много не мења, али то ствара пут за будуће еволуције. Такође морамо ажурирати функције које га користе. У функцијама `register()` и `login()`, замените `account = ...` са `state.account = ...`; @@ -85,17 +85,17 @@ let state = { const account = state.account; ``` -Ово рефакторисање само по себи није донело много побољшања, али идеја је била да се поставе темељи за следеће промене. +Ово рефакторисање само по себи није донело много побољшања, али идеја је била да се постави основа за следеће промене. ## Праћење промена података Сада када смо поставили објекат `state` за чување наших података, следећи корак је централизовање ажурирања. Циљ је да се олакша праћење било каквих промена и када се оне дешавају. -Да бисмо избегли промене направљене у објекту `state`, добра је пракса да га сматрамо [*непроменљивим*](https://en.wikipedia.org/wiki/Immutable_object), што значи да се уопште не може мењати. Ово такође значи да морате креирати нови објекат стања ако желите да промените било шта у њему. На овај начин градите заштиту од потенцијално нежељених [нуспојава](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) и отварате могућности за нове функције у вашој апликацији, као што је имплементација поништавања/поновног извршавања, док такође олакшавате отклањање грешака. На пример, могли бисте бележити сваку промену направљену у стању и чувати историју промена како бисте разумели извор грешке. +Да бисмо избегли промене направљене на објекту `state`, такође је добра пракса да га сматрамо [*непроменљивим*](https://en.wikipedia.org/wiki/Immutable_object), што значи да се уопште не може мењати. То такође значи да морате креирати нови објекат стања ако желите да промените било шта у њему. На овај начин градите заштиту од потенцијално нежељених [споредних ефеката](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) за креирање непроменљиве верзије објекта. Ако покушате да направите промене у непроменљивом објекту, биће подигнут изузетак. +У JavaScript-у можете користити [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) да креирате непроменљиву верзију објекта. Ако покушате да направите промене на непроменљивом објекту, биће подигнута изузетак. -✅ Знате ли разлику између *плитког* и *дубоког* непроменљивог објекта? Можете прочитати о томе [овде](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Да ли знате разлику између *плитког* и *дубоког* непроменљивог објекта? Можете прочитати о томе [овде](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Задатак @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -У овој функцији креирамо нови објекат стања и копирамо податке из претходног стања користећи [*spread (`...`) оператор*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Затим замењујемо одређено својство објекта стања новим подацима користећи [нотацију са заградама](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` за доделу. На крају, закључавамо објекат како бисмо спречили модификације користећи `Object.freeze()`. Тренутно у стању чувамо само својство `account`, али са овим приступом можете додати онолико својстава колико вам је потребно. +У овој функцији креирамо нови објекат стања и копирамо податке из претходног стања користећи [*оператор ширења (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Затим замењујемо одређено својство објекта стања новим подацима користећи [нотацију са заградама](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` за доделу. На крају, закључавамо објекат како бисмо спречили модификације користећи `Object.freeze()`. Тренутно имамо само својство `account` у стању, али са овим приступом можете додати онолико својстава колико вам је потребно у стање. -Такође ћемо ажурирати иницијализацију `state` како бисмо били сигурни да је почетно стање такође закључано: +Такође ћемо ажурирати иницијализацију `state` како бисмо били сигурни да је почетно стање такође замрзнуто: ```js let state = Object.freeze({ @@ -120,19 +120,19 @@ let state = Object.freeze({ }); ``` -Након тога, ажурирајте функцију `register` тако што ћете заменити доделу `state.account = result;` са: +Након тога, ажурирајте функцију `register` заменом доделе `state.account = result;` са: ```js updateState('account', result); ``` -Урадите исто са функцијом `login`, заменивши `state.account = data;` са: +Урадите исто са функцијом `login`, заменом `state.account = data;` са: ```js updateState('account', data); ``` -Сада ћемо искористити прилику да решимо проблем са подацима о налогу који се не бришу када корисник кликне на *Одјава*. +Сада ћемо искористити прилику да решимо проблем да подаци о налогу нису очишћени када корисник кликне на *Одјави се*. Креирајте нову функцију `logout()`: @@ -143,35 +143,35 @@ function logout() { } ``` -У `updateDashboard()`, замените преусмеравање `return navigate('/login');` са `return logout();`. +У функцији `updateDashboard()`, замените преусмеравање `return navigate('/login');` са `return logout();` -Покушајте да региструјете нови налог, одјавите се и поново пријавите како бисте проверили да ли све и даље ради исправно. +Покушајте да региструјете нови налог, одјавите се и поново пријавите да бисте проверили да ли све и даље ради исправно. -> Савет: можете погледати све промене стања додавањем `console.log(state)` на крају `updateState()` и отварањем конзоле у алатима за развој вашег прегледача. +> Савет: можете погледати све промене стања додавањем `console.log(state)` на крај функције `updateState()` и отварањем конзоле у алатима за развој вашег прегледача. ## Чување стања -Већини веб апликација је потребно да чувају податке како би исправно функционисале. Сви критични подаци обично се чувају у бази података и приступа им се преко серверског API-ја, као што су подаци о корисничком налогу у нашем случају. Али понекад је такође занимљиво чувати неке податке на клијентској апликацији која ради у вашем прегледачу, ради бољег корисничког искуства или побољшања перформанси учитавања. +Већини веб апликација је потребно да чувају податке како би исправно функционисале. Сви критични подаци обично се чувају у бази података и приступа им се преко серверског API-ја, као што су подаци о корисничком налогу у нашем случају. Али понекад је такође занимљиво чувати неке податке на клијентској апликацији која ради у вашем прегледачу, ради бољег корисничког искуства или ради побољшања перформанси учитавања. Када желите да чувате податке у вашем прегледачу, постоји неколико важних питања која треба да поставите себи: -- *Да ли су подаци осетљиви?* Требало би избегавати чување било каквих осетљивих података на клијенту, као што су корисничке лозинке. -- *Колико дуго вам је потребно да задржите ове податке?* Да ли планирате да приступате овим подацима само током тренутне сесије или желите да их чувате заувек? +- *Да ли су подаци осетљиви?* Требало би да избегавате чување било каквих осетљивих података на клијенту, као што су корисничке лозинке. +- *Колико дуго вам је потребно да задржите ове податке?* Да ли планирате да приступите овим подацима само током тренутне сесије или желите да их чувате заувек? -Постоји више начина за чување информација унутар веб апликације, у зависности од тога шта желите да постигнете. На пример, можете користити URL-ове за чување упита за претрагу и учинити их доступним за дељење између корисника. Такође можете користити [HTTP колачиће](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ако подаци треба да се деле са сервером, као што су информације о [аутентификацији](https://en.wikipedia.org/wiki/Authentication). +Постоји више начина за чување информација унутар веб апликације, у зависности од тога шта желите да постигнете. На пример, можете користити URL-ове за чување упита за претрагу и учинити их деливим између корисника. Такође можете користити [HTTP колачиће](https://developer.mozilla.org/docs/Web/HTTP/Cookies) ако подаци треба да се деле са сервером, као што су информације о [аутентификацији](https://en.wikipedia.org/wiki/Authentication). -Друга опција је коришћење једног од многих API-ја прегледача за чување података. Два су посебно занимљива: +Друга опција је коришћење једног од многих API-ја прегледача за чување података. Два од њих су посебно занимљива: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Key/Value складиште](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) које омогућава чување података специфичних за тренутни веб сајт током различитих сесија. Подаци сачувани у њему никада не истичу. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): ово ради исто као `localStorage`, осим што се подаци сачувани у њему бришу када се сесија заврши (када се прегледач затвори). +- [`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-ја дозвољавају чување само [стрингова](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Ако желите да чувате сложене објекте, мораћете да их серијализујете у [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) формат користећи [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Ако желите да направите веб апликацију која не ради са сервером, могуће је направити базу података на клијенту користећи [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Ово је резервисано за напредне случајеве употребе или ако треба да чувате значајну количину података, јер је сложеније за коришћење. +✅ Ако желите да креирате веб апликацију која не ради са сервером, могуће је креирати базу података на клијенту користећи [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Овај је резервисан за напредне случајеве употребе или ако треба да чувате значајну количину података, јер је сложенији за употребу. ### Задатак -Желимо да наши корисници остану пријављени док експлицитно не кликну на дугме *Одјава*, па ћемо користити `localStorage` за чување података о налогу. Прво, хајде да дефинишемо кључ који ћемо користити за чување наших података. +Желимо да наши корисници остану пријављени док експлицитно не кликну на дугме *Одјави се*, па ћемо користити `localStorage` за чување података о налогу. Прво, хајде да дефинишемо кључ који ћемо користити за чување наших података. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ const storageKey = 'savedAccount'; localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Са овим, подаци о корисничком налогу ће бити сачувани и увек ажурирани јер смо претходно централизовали сва наша ажурирања стања. Овде почињемо да уживамо у предностима свих наших претходних рефакторисања 🙂. +Са овим, подаци о корисничком налогу ће бити сачувани и увек ажурирани, јер смо претходно централизовали сва наша ажурирања стања. Овде почињемо да уживамо у предностима свих наших претходних рефакторисања 🙂. -Како су подаци сачувани, такође морамо водити рачуна о њиховом враћању када се апликација учита. Пошто ћемо почети да имамо више кода за иницијализацију, можда је добра идеја да направимо нову функцију `init`, која такође укључује наш претходни код на крају `app.js`: +Како су подаци сачувани, такође морамо водити рачуна о њиховом враћању када се апликација учита. Пошто ћемо почети да имамо више кода за иницијализацију, можда је добра идеја да креирамо нову функцију `init`, која такође укључује наш претходни код на крају `app.js`: ```js function init() { @@ -204,13 +204,13 @@ init(); Овде враћамо сачуване податке, и ако их има, ажурирамо стање у складу с тим. Важно је то урадити *пре* ажурирања руте, јер може постојати код који се ослања на стање током ажурирања странице. -Такође можемо направити страницу *Контролна табла* подразумеваном страницом наше апликације, јер сада чувамо податке о налогу. Ако подаци нису пронађени, контролна табла се брине о преусмеравању на страницу *Пријава*. У `updateRoute()`, замените резервну `return navigate('/login');` са `return navigate('/dashboard');`. +Такође можемо учинити страницу *Контролна табла* подразумеваном страницом наше апликације, јер сада чувамо податке о налогу. Ако подаци нису пронађени, контролна табла се брине о преусмеравању на страницу *Пријава*. У функцији `updateRoute()`, замените резервну опцију `return navigate('/login');` са `return navigate('/dashboard');`. -Сада се пријавите у апликацију и покушајте да освежите страницу. Требало би да останете на контролној табли. Са овим ажурирањем решили смо све наше почетне проблеме... +Сада се пријавите у апликацију и покушајте да освежите страницу. Требало би да останете на контролној табли. Са тим ажурирањем решили смо све наше почетне проблеме... ## Освежавање података -...Али можда смо створили нови проблем. Опа! +...Али можда смо такође створили нови проблем. Опа! Идите на контролну таблу користећи налог `test`, а затим покрените ову команду у терминалу да бисте креирали нову трансакцију: @@ -223,7 +223,7 @@ curl --request POST \ Покушајте да освежите страницу контролне табле у прегледачу сада. Шта се дешава? Да ли видите нову трансакцију? -Стање је сачувано на неодређено време захваљујући `localStorage`, али то такође значи да се никада не ажурира док се не одјавите из апликације и поново пријавите! +Стање се чува на неодређено време захваљујући `localStorage`, али то такође значи да се никада не ажурира док се не одјавите из апликације и поново пријавите! Једна могућа стратегија за решавање овог проблема је да се подаци о налогу поново учитавају сваки пут када се контролна табла учита, како би се избегли застарели подаци. @@ -249,7 +249,7 @@ async function updateAccountData() { Ова метода проверава да ли сте тренутно пријављени, а затим поново учитава податке о налогу са сервера. -Креирајте још једну функцију под називом `refresh`: +Креирајте другу функцију под називом `refresh`: ```js async function refresh() { @@ -258,14 +258,18 @@ async function refresh() { } ``` -Ова функција ажурира податке -[Implementacija dijaloga "Dodaj transakciju"](assignment.md) +Ова функција ажур +[Квиз након предавања](https://ff-quizzes.netlify.app/web/quiz/48) -Evo primera rezultata nakon završetka zadatka: +## Задатак -![Snimak ekrana koji prikazuje primer dijaloga "Dodaj transakciju"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sr.png) +[Имплементирајте дијалог "Додај трансакцију"](assignment.md) + +Ево примера резултата након завршетка задатка: + +![Снимак екрана који приказује пример дијалога "Додај трансакцију"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sr.png) --- **Одрицање од одговорности**: -Овај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције [Co-op Translator](https://github.com/Azure/co-op-translator). Иако тежимо тачности, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на изворном језику треба сматрати ауторитативним извором. За критичне информације препоручује се професионални превод од стране људи. Не сносимо одговорност за било каква неспоразумевања или погрешна тумачења која могу произаћи из коришћења овог превода. \ No newline at end of file +Овај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције [Co-op Translator](https://github.com/Azure/co-op-translator). Иако тежимо тачности, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на изворном језику треба сматрати ауторитативним извором. За критичне информације препоручује се професионални превод од стране људи. Не сносимо одговорност за било каква погрешна тумачења или неспоразуме који могу настати услед коришћења овог превода. \ No newline at end of file diff --git a/translations/sv/7-bank-project/4-state-management/README.md b/translations/sv/7-bank-project/4-state-management/README.md index b2baf7a9c..7fd30c795 100644 --- a/translations/sv/7-bank-project/4-state-management/README.md +++ b/translations/sv/7-bank-project/4-state-management/README.md @@ -1,29 +1,29 @@ -# Bygg en Bankapp Del 4: Koncept för Tillståndshantering +# Bygg en Bankapp Del 4: Koncept för State Management -## Förkunskapstest +## Förhandsquiz -[Förkunskapstest](https://ff-quizzes.netlify.app/web/quiz/47) +[Förhandsquiz](https://ff-quizzes.netlify.app/web/quiz/47) ### Introduktion -När en webbapplikation växer blir det en utmaning att hålla reda på alla dataflöden. Vilken kod hämtar datan, vilken sida använder den, var och när behöver den uppdateras... det är lätt att hamna med rörig kod som är svår att underhålla. Detta är särskilt sant när du behöver dela data mellan olika sidor i din app, till exempel användardata. Konceptet *tillståndshantering* har alltid funnits i alla typer av program, men eftersom webbappar blir alltmer komplexa är det nu en nyckelfråga att tänka på under utvecklingen. +När en webbapplikation växer blir det en utmaning att hålla reda på alla dataflöden. Vilken kod hämtar datan, vilken sida använder den, var och när behöver den uppdateras...det är lätt att hamna med rörig kod som är svår att underhålla. Detta är särskilt sant när du behöver dela data mellan olika sidor i din app, till exempel användardata. Konceptet *state management* har alltid funnits i alla typer av program, men eftersom webbappar fortsätter att öka i komplexitet är det nu en viktig punkt att tänka på under utvecklingen. -I denna sista del kommer vi att granska appen vi byggt för att omvärdera hur tillstånd hanteras, vilket möjliggör stöd för att uppdatera webbläsaren när som helst och bevara data mellan användarsessioner. +I denna sista del kommer vi att granska appen vi byggde för att ompröva hur staten hanteras, vilket möjliggör stöd för webbläsaruppdatering när som helst och att data kvarstår över användarsessioner. ### Förutsättningar -Du behöver ha slutfört [datahämtning](../3-data/README.md)-delen av webbappen för denna lektion. Du behöver också installera [Node.js](https://nodejs.org) och [köra server-API:t](../api/README.md) lokalt så att du kan hantera kontodata. +Du måste ha slutfört [datahämtning](../3-data/README.md)-delen av webbappen för denna lektion. Du måste också installera [Node.js](https://nodejs.org) och [köra server-API:t](../api/README.md) lokalt så att du kan hantera kontodata. -Du kan testa att servern fungerar korrekt genom att köra detta kommando i en terminal: +Du kan testa att servern körs korrekt genom att köra detta kommando i en terminal: ```sh curl http://localhost:5000/api @@ -32,32 +32,32 @@ curl http://localhost:5000/api --- -## Omvärdera tillståndshantering +## Ompröva state management -I [föregående lektion](../3-data/README.md) introducerade vi ett grundläggande koncept för tillstånd i vår app med den globala variabeln `account` som innehåller bankdatan för den inloggade användaren. Men vår nuvarande implementation har vissa brister. Försök att uppdatera sidan när du är på instrumentpanelen. Vad händer? +I [föregående lektion](../3-data/README.md) introducerade vi ett grundläggande koncept för state i vår app med den globala variabeln `account` som innehåller bankdata för den aktuella inloggade användaren. Men vår nuvarande implementation har vissa brister. Försök att uppdatera sidan när du är på instrumentpanelen. Vad händer? Det finns tre problem med den nuvarande koden: -- Tillståndet sparas inte, eftersom en uppdatering av webbläsaren tar dig tillbaka till inloggningssidan. -- Det finns flera funktioner som ändrar tillståndet. När appen växer kan det bli svårt att hålla reda på ändringarna och lätt att glömma att uppdatera något. -- Tillståndet rensas inte, så när du klickar på *Logga ut* finns kontodatan fortfarande kvar även om du är på inloggningssidan. +- Staten sparas inte, eftersom en webbläsaruppdatering tar dig tillbaka till inloggningssidan. +- Det finns flera funktioner som ändrar staten. När appen växer kan det bli svårt att spåra ändringarna och det är lätt att glömma att uppdatera en. +- Staten rensas inte, så när du klickar på *Logga ut* finns kontodata fortfarande kvar även om du är på inloggningssidan. -Vi skulle kunna uppdatera vår kod för att lösa dessa problem ett i taget, men det skulle skapa mer kodupprepning och göra appen mer komplex och svår att underhålla. Eller så kan vi pausa i några minuter och omvärdera vår strategi. +Vi skulle kunna uppdatera vår kod för att hantera dessa problem ett i taget, men det skulle skapa mer kodduplicering och göra appen mer komplex och svår att underhålla. Eller så kan vi pausa några minuter och ompröva vår strategi. > Vilka problem försöker vi egentligen lösa här? -[Tillståndshantering](https://en.wikipedia.org/wiki/State_management) handlar om att hitta ett bra sätt att lösa dessa två specifika problem: +[State management](https://en.wikipedia.org/wiki/State_management) handlar om att hitta en bra metod för att lösa dessa två specifika problem: -- Hur håller vi dataflödena i en app begripliga? -- Hur håller vi tillståndsdata alltid synkroniserade med användargränssnittet (och vice versa)? +- Hur håller man dataflödena i en app begripliga? +- Hur håller man state-data alltid synkroniserad med användargränssnittet (och vice versa)? -När du har tagit hand om dessa kan andra problem antingen redan vara lösta eller bli enklare att lösa. Det finns många möjliga tillvägagångssätt för att lösa dessa problem, men vi kommer att använda en vanlig lösning som består av att **centralisera datan och sätten att ändra den**. Dataflödena skulle se ut så här: +När du har tagit hand om dessa kan eventuella andra problem du har antingen redan vara lösta eller ha blivit enklare att lösa. Det finns många möjliga metoder för att lösa dessa problem, men vi kommer att använda en vanlig lösning som består av att **centralisera data och sätt att ändra den**. Dataflödena skulle se ut så här: -![Schema som visar dataflöden mellan HTML, användaråtgärder och tillstånd](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.sv.png) +![Schema som visar dataflöden mellan HTML, användaråtgärder och state](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.sv.png) -> Vi kommer inte att täcka delen där data automatiskt uppdaterar vyn, eftersom det är kopplat till mer avancerade koncept inom [Reaktiv Programmering](https://en.wikipedia.org/wiki/Reactive_programming). Det är ett bra ämne att fördjupa sig i om du vill gå djupare. +> Vi kommer inte att täcka den del där data automatiskt triggar uppdatering av vyn, eftersom det är kopplat till mer avancerade koncept inom [Reaktiv Programmering](https://en.wikipedia.org/wiki/Reactive_programming). Det är ett bra ämne att fördjupa sig i om du är intresserad. -✅ Det finns många bibliotek där ute med olika tillvägagångssätt för tillståndshantering, [Redux](https://redux.js.org) är ett populärt alternativ. Ta en titt på koncepten och mönstren som används, eftersom det ofta är ett bra sätt att lära sig vilka potentiella problem du kan stöta på i stora webbappar och hur de kan lösas. +✅ Det finns många bibliotek där ute med olika metoder för state management, [Redux](https://redux.js.org) är ett populärt alternativ. Ta en titt på koncepten och mönstren som används eftersom det ofta är ett bra sätt att lära sig vilka potentiella problem du kan stöta på i stora webbappar och hur de kan lösas. ### Uppgift @@ -75,9 +75,9 @@ let state = { }; ``` -Tanken är att *centralisera* all vår appdata i ett enda tillståndsobjekt. Vi har bara `account` för tillfället i tillståndet, så det förändrar inte mycket, men det skapar en väg för framtida utveckling. +Idén är att *centralisera* all vår appdata i ett enda state-objekt. Vi har bara `account` för tillfället i staten så det förändrar inte mycket, men det skapar en väg för framtida utveckling. -Vi måste också uppdatera funktionerna som använder det. I funktionerna `register()` och `login()`, ersätt `account = ...` med `state.account = ...`; +Vi måste också uppdatera funktionerna som använder det. I funktionerna `register()` och `login()` ersätt `account = ...` med `state.account = ...`; Lägg till denna rad högst upp i funktionen `updateDashboard()`: @@ -85,17 +85,17 @@ Lägg till denna rad högst upp i funktionen `updateDashboard()`: const account = state.account; ``` -Denna omstrukturering i sig gav inte så stora förbättringar, men tanken var att lägga grunden för de kommande ändringarna. +Denna omstrukturering i sig gav inte mycket förbättringar, men idén var att lägga grunden för nästa förändringar. ## Spåra dataändringar -Nu när vi har infört objektet `state` för att lagra vår data är nästa steg att centralisera uppdateringarna. Målet är att göra det enklare att hålla reda på alla ändringar och när de sker. +Nu när vi har infört `state`-objektet för att lagra vår data är nästa steg att centralisera uppdateringarna. Målet är att göra det enklare att hålla reda på alla ändringar och när de sker. -För att undvika att ändringar görs direkt i objektet `state` är det också en bra praxis att betrakta det som [*oföränderligt*](https://en.wikipedia.org/wiki/Immutable_object), vilket innebär att det inte kan ändras alls. Det innebär också att du måste skapa ett nytt tillståndsobjekt om du vill ändra något i det. Genom att göra detta bygger du ett skydd mot potentiellt oönskade [bieffekter](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) och öppnar upp möjligheter för nya funktioner i din app, som att implementera ångra/gör om, samtidigt som det blir enklare att felsöka. Till exempel kan du logga varje ändring som görs i tillståndet och hålla en historik över ändringarna för att förstå källan till ett fel. +För att undvika att ändringar görs direkt i `state`-objektet är det också en bra praxis att betrakta det som [*oföränderligt*](https://en.wikipedia.org/wiki/Immutable_object), vilket innebär att det inte kan ändras alls. Det innebär också att du måste skapa ett nytt state-objekt om du vill ändra något i det. Genom att göra detta bygger du ett skydd mot potentiellt oönskade [bieffekter](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) och öppnar upp möjligheter för nya funktioner i din app, som att implementera ångra/göra om, samtidigt som det blir enklare att felsöka. Till exempel kan du logga varje ändring som görs i staten och hålla en historik över ändringarna för att förstå källan till ett fel. I JavaScript kan du använda [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) för att skapa en oföränderlig version av ett objekt. Om du försöker göra ändringar i ett oföränderligt objekt kommer ett undantag att kastas. -✅ Vet du skillnaden mellan ett *ytligt* och ett *djupt* oföränderligt objekt? Du kan läsa om det [här](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). +✅ Vet du skillnaden mellan ett *ytligt* och ett *djupgående* oföränderligt objekt? Du kan läsa om det [här](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). ### Uppgift @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -I denna funktion skapar vi ett nytt tillståndsobjekt och kopierar data från det tidigare tillståndet med hjälp av [*spridningsoperatorn (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Sedan skriver vi över en specifik egenskap i tillståndsobjektet med den nya datan med hjälp av [haknotationen](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` för tilldelning. Slutligen låser vi objektet för att förhindra ändringar med `Object.freeze()`. Vi har bara egenskapen `account` lagrad i tillståndet för tillfället, men med detta tillvägagångssätt kan du lägga till så många egenskaper som du behöver i tillståndet. +I denna funktion skapar vi ett nytt state-objekt och kopierar data från det tidigare state med hjälp av [*spridningsoperatorn (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Sedan skriver vi över en specifik egenskap i state-objektet med den nya datan med hjälp av [haknotationen](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` för tilldelning. Slutligen låser vi objektet för att förhindra ändringar med `Object.freeze()`. Vi har bara egenskapen `account` lagrad i staten för tillfället, men med denna metod kan du lägga till så många egenskaper som du behöver i staten. -Vi uppdaterar också initialiseringen av `state` för att säkerställa att det initiala tillståndet också är fryst: +Vi kommer också att uppdatera initialiseringen av `state` för att säkerställa att det initiala state är fryst också: ```js let state = Object.freeze({ @@ -132,7 +132,7 @@ Gör samma sak med funktionen `login`, ersätt `state.account = data;` med: updateState('account', data); ``` -Vi passar nu på att lösa problemet med att kontodatan inte rensas när användaren klickar på *Logga ut*. +Vi tar nu tillfället i akt att lösa problemet med att kontodata inte rensas när användaren klickar på *Logga ut*. Skapa en ny funktion `logout()`: @@ -143,35 +143,35 @@ function logout() { } ``` -I `updateDashboard()`, ersätt omdirigeringen `return navigate('/login');` med `return logout();`. +I `updateDashboard()`, ersätt omdirigeringen `return navigate('/login');` med `return logout();` Försök att registrera ett nytt konto, logga ut och logga in igen för att kontrollera att allt fortfarande fungerar korrekt. -> Tips: Du kan titta på alla tillståndsändringar genom att lägga till `console.log(state)` längst ner i `updateState()` och öppna konsolen i din webbläsares utvecklingsverktyg. +> Tips: du kan titta på alla state-ändringar genom att lägga till `console.log(state)` längst ner i `updateState()` och öppna konsolen i din webbläsares utvecklingsverktyg. -## Bevara tillståndet +## Spara staten -De flesta webbappar behöver bevara data för att fungera korrekt. All kritisk data lagras vanligtvis i en databas och nås via ett server-API, som användarkontodata i vårt fall. Men ibland är det också intressant att bevara viss data i klientappen som körs i din webbläsare, för en bättre användarupplevelse eller för att förbättra laddningsprestandan. +De flesta webbappar behöver spara data för att kunna fungera korrekt. All kritisk data lagras vanligtvis i en databas och nås via ett server-API, som användarkontodata i vårt fall. Men ibland kan det också vara intressant att spara viss data i klientappen som körs i din webbläsare, för en bättre användarupplevelse eller för att förbättra laddningsprestandan. -När du vill bevara data i din webbläsare finns det några viktiga frågor du bör ställa dig: +När du vill spara data i din webbläsare finns det några viktiga frågor du bör ställa dig: -- *Är datan känslig?* Du bör undvika att lagra känslig data på klienten, som användarlösenord. -- *Hur länge behöver du behålla denna data?* Planerar du att använda denna data endast under den aktuella sessionen eller vill du att den ska lagras för alltid? +- *Är datan känslig?* Du bör undvika att lagra känslig data på klienten, såsom användarlösenord. +- *Hur länge behöver du behålla denna data?* Planerar du att använda denna data endast för den aktuella sessionen eller vill du att den ska lagras för alltid? Det finns flera sätt att lagra information i en webbapp, beroende på vad du vill uppnå. Till exempel kan du använda URL:er för att lagra en sökfråga och göra den delbar mellan användare. Du kan också använda [HTTP-cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) om datan behöver delas med servern, som [autentiseringsinformation](https://en.wikipedia.org/wiki/Authentication). Ett annat alternativ är att använda en av de många webbläsar-API:erna för att lagra data. Två av dem är särskilt intressanta: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Nyckel/Värde-lagring](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) som gör det möjligt att bevara data specifik för den aktuella webbplatsen mellan olika sessioner. Datan som sparas i den upphör aldrig att gälla. +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): en [Key/Value store](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) som gör det möjligt att spara data specifik för den aktuella webbplatsen över olika sessioner. Datan som sparas i den upphör aldrig. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): denna fungerar på samma sätt som `localStorage` förutom att datan som lagras i den rensas när sessionen avslutas (när webbläsaren stängs). -Observera att båda dessa API:er endast tillåter lagring av [strängar](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Om du vill lagra komplexa objekt måste du serialisera dem till [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formatet med [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Observera att båda dessa API:er endast tillåter att lagra [strängar](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Om du vill lagra komplexa objekt måste du serialisera dem till [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)-formatet med [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Om du vill skapa en webbapp som inte fungerar med en server är det också möjligt att skapa en databas på klienten med hjälp av [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Detta är reserverat för avancerade användningsfall eller om du behöver lagra en betydande mängd data, eftersom det är mer komplext att använda. +✅ Om du vill skapa en webbapp som inte fungerar med en server är det också möjligt att skapa en databas på klienten med [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Detta är reserverat för avancerade användningsfall eller om du behöver lagra betydande mängder data, eftersom det är mer komplext att använda. ### Uppgift -Vi vill att våra användare ska förbli inloggade tills de uttryckligen klickar på knappen *Logga ut*, så vi kommer att använda `localStorage` för att lagra kontodatan. Först definierar vi en nyckel som vi kommer att använda för att lagra vår data. +Vi vill att våra användare ska förbli inloggade tills de uttryckligen klickar på *Logga ut*-knappen, så vi kommer att använda `localStorage` för att lagra kontodata. Först, låt oss definiera en nyckel som vi kommer att använda för att lagra vår data. ```js const storageKey = 'savedAccount'; @@ -183,9 +183,9 @@ Lägg sedan till denna rad i slutet av funktionen `updateState()`: localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Med detta kommer användarkontodatan att bevaras och alltid vara uppdaterad eftersom vi tidigare centraliserade alla våra tillståndsuppdateringar. Det är här vi börjar dra nytta av alla våra tidigare omstruktureringar 🙂. +Med detta kommer användarkontodata att sparas och alltid vara uppdaterad eftersom vi tidigare centraliserade alla våra state-uppdateringar. Det är här vi börjar dra nytta av alla våra tidigare omstruktureringar 🙂. -Eftersom datan sparas måste vi också ta hand om att återställa den när appen laddas. Eftersom vi börjar få mer initialiseringskod kan det vara en bra idé att skapa en ny funktion `init`, som också inkluderar vår tidigare kod längst ner i `app.js`: +Eftersom datan sparas måste vi också ta hand om att återställa den när appen laddas. Eftersom vi börjar få mer initialiseringskod kan det vara en bra idé att skapa en ny `init`-funktion, som också inkluderar vår tidigare kod längst ner i `app.js`: ```js function init() { @@ -202,9 +202,9 @@ function init() { init(); ``` -Här hämtar vi den sparade datan, och om det finns någon uppdaterar vi tillståndet därefter. Det är viktigt att göra detta *innan* vi uppdaterar routen, eftersom det kan finnas kod som förlitar sig på tillståndet under siduppdateringen. +Här hämtar vi den sparade datan, och om det finns någon uppdaterar vi staten därefter. Det är viktigt att göra detta *innan* vi uppdaterar routen, eftersom det kan finnas kod som förlitar sig på staten under siduppdateringen. -Vi kan också göra *Instrumentpanelen* till vår applikations standardsida, eftersom vi nu bevarar kontodatan. Om ingen data hittas tar instrumentpanelen hand om att omdirigera till *Inloggningssidan* ändå. I `updateRoute()`, ersätt fallbacken `return navigate('/login');` med `return navigate('/dashboard');`. +Vi kan också göra *Dashboard*-sidan till vår applikations standardsida, eftersom vi nu sparar kontodata. Om ingen data hittas tar instrumentpanelen hand om att omdirigera till *Login*-sidan ändå. I `updateRoute()`, ersätt fallbacken `return navigate('/login');` med `return navigate('/dashboard');`. Logga nu in i appen och försök att uppdatera sidan. Du bör stanna kvar på instrumentpanelen. Med den uppdateringen har vi tagit hand om alla våra ursprungliga problem... @@ -221,9 +221,9 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Försök att uppdatera instrumentpanelen i webbläsaren nu. Vad händer? Ser du den nya transaktionen? +Försök att uppdatera din instrumentpanelsida i webbläsaren nu. Vad händer? Ser du den nya transaktionen? -Tillståndet bevaras på obestämd tid tack vare `localStorage`, men det betyder också att det aldrig uppdateras förrän du loggar ut ur appen och loggar in igen! +Staten sparas på obestämd tid tack vare `localStorage`, men det betyder också att den aldrig uppdateras förrän du loggar ut från appen och loggar in igen! En möjlig strategi för att lösa detta är att ladda om kontodatan varje gång instrumentpanelen laddas, för att undvika föråldrad data. @@ -258,7 +258,7 @@ async function refresh() { } ``` -Denna funktion uppdaterar kontodatan och tar sedan hand om att uppdatera HTML:en på instrumentpanelsidan. Det är vad vi behöver kalla på när routen för instrumentpanelen laddas. Uppdatera routedefinitionen med: +Denna uppdaterar kontodatan och tar sedan hand om att uppdatera HTML:en på instrumentpanelsidan. Det är vad vi behöver kalla på när instrumentpanelens route laddas. Uppdatera routedefinitionen med: ```js const routes = { @@ -273,22 +273,22 @@ Försök att ladda om instrumentpanelen nu, den bör visa den uppdaterade kontod ## 🚀 Utmaning -Nu när vi laddar om kontodatan varje gång instrumentpanelen laddas, tror du att vi fortfarande behöver bevara *all kontodata*? +Nu när vi laddar om kontodatan varje gång instrumentpanelen laddas, tror du att vi fortfarande behöver spara *hela kontodatan*? -Försök att arbeta tillsammans för att ändra vad som sparas och laddas från `localStorage` så att det endast inkluderar det som är absolut nödvändigt för att appen ska fungera. +Försök att arbeta tillsammans för att ändra vad som sparas och laddas från `localStorage` till att endast inkludera det som är absolut nödvändigt för att appen ska fungera. -## Efterföreläsningstest - -[Efterföreläsningstest](https://ff-quizzes.netlify.app/web/quiz/48) +## Efterföreläsningsquiz +[Quiz efter föreläsningen](https://ff-quizzes.netlify.app/web/quiz/48) ## Uppgift -[Implementera dialogrutan "Lägg till transaktion"](assignment.md) -Här är ett exempelresultat efter att uppgiften har slutförts: +[Implementera dialogen "Lägg till transaktion"](assignment.md) + +Här är ett exempel på resultat efter att ha slutfört uppgiften: -![Skärmdump som visar ett exempel på dialogrutan "Lägg till transaktion"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sv.png) +![Skärmdump som visar ett exempel på dialogen "Lägg till transaktion"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.sv.png) --- **Ansvarsfriskrivning**: -Detta dokument har översatts med hjälp av AI-översättningstjänsten [Co-op Translator](https://github.com/Azure/co-op-translator). Även om vi strävar efter noggrannhet, bör du vara medveten om att automatiserade översättningar kan innehålla fel eller inexaktheter. Det ursprungliga dokumentet på dess ursprungliga språk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning. \ No newline at end of file +Detta dokument har översatts med hjälp av AI-översättningstjänsten [Co-op Translator](https://github.com/Azure/co-op-translator). Även om vi strävar efter noggrannhet, bör det noteras att automatiserade översättningar kan innehålla fel eller felaktigheter. Det ursprungliga dokumentet på dess originalspråk bör betraktas som den auktoritativa källan. För kritisk information rekommenderas professionell mänsklig översättning. Vi ansvarar inte för eventuella missförstånd eller feltolkningar som uppstår vid användning av denna översättning. \ No newline at end of file diff --git a/translations/sw/7-bank-project/4-state-management/README.md b/translations/sw/7-bank-project/4-state-management/README.md index 88716dcc5..cb1cd48cd 100644 --- a/translations/sw/7-bank-project/4-state-management/README.md +++ b/translations/sw/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Bankacılık Uygulaması Yapımı Bölüm 4: Durum Yönetimi Kavramları +# Bir Bankacılık Uygulaması Oluşturma Bölüm 4: Durum Yönetimi Kavramları ## Ders Öncesi Test @@ -15,7 +15,7 @@ CO_OP_TRANSLATOR_METADATA: ### Giriş -Bir web uygulaması büyüdükçe, tüm veri akışlarını takip etmek zorlaşır. Hangi kod veriyi alıyor, hangi sayfa bunu tüketiyor, nerede ve ne zaman güncellenmesi gerekiyor... Kodun karmaşıklaşması ve bakımının zorlaşması kolaydır. Bu durum, özellikle uygulamanızın farklı sayfaları arasında veri paylaşmanız gerektiğinde, örneğin kullanıcı verileri gibi, daha da belirgin hale gelir. *Durum yönetimi* kavramı her tür programda her zaman var olmuştur, ancak web uygulamaları karmaşıklık açısından büyüdükçe, geliştirme sırasında düşünülmesi gereken önemli bir nokta haline gelmiştir. +Bir web uygulaması büyüdükçe, tüm veri akışlarını takip etmek zorlaşır. Hangi kod veriyi alıyor, hangi sayfa bunu kullanıyor, nerede ve ne zaman güncellenmesi gerekiyor... karmaşık ve zor yönetilebilir bir kod yığınına dönüşmek kolaydır. Bu durum, özellikle uygulamanızın farklı sayfaları arasında veri paylaşmanız gerektiğinde, örneğin kullanıcı verileri gibi, daha da belirgin hale gelir. *Durum yönetimi* kavramı her tür programda her zaman var olmuştur, ancak web uygulamaları karmaşıklık açısından büyüdükçe, artık geliştirme sırasında düşünülmesi gereken önemli bir nokta haline gelmiştir. Bu son bölümde, oluşturduğumuz uygulamayı gözden geçirerek durumun nasıl yönetildiğini yeniden düşüneceğiz. Bu, tarayıcı yenilemesini herhangi bir noktada desteklemeyi ve kullanıcı oturumları arasında verileri kalıcı hale getirmeyi sağlayacaktır. @@ -32,30 +32,30 @@ curl http://localhost:5000/api --- -## Durum yönetimini yeniden düşünmek +## Durum Yönetimini Yeniden Düşünmek -[Önceki derste](../3-data/README.md), uygulamamızda şu anda oturum açmış kullanıcıya ait banka verilerini içeren global `account` değişkeni ile durumun temel bir kavramını tanıttık. Ancak, mevcut uygulamamızda bazı eksiklikler var. Dashboard sayfasındayken sayfayı yenilemeyi deneyin. Ne oluyor? +[Önceki derste](../3-data/README.md), uygulamamızda şu anda oturum açmış kullanıcıya ait banka verilerini içeren global `account` değişkeni ile temel bir durum kavramını tanıttık. Ancak, mevcut uygulamamızda bazı eksiklikler var. Dashboard sayfasındayken sayfayı yenilemeyi deneyin. Ne oluyor? Mevcut kodda 3 sorun var: -- Durum kalıcı değil, çünkü tarayıcı yenilemesi sizi giriş sayfasına geri götürüyor. -- Durumu değiştiren birden fazla işlev var. Uygulama büyüdükçe, değişiklikleri takip etmek zorlaşabilir ve birini güncellemeyi unutmak kolaydır. -- Durum temizlenmiyor, bu yüzden *Çıkış Yap* düğmesine tıkladığınızda, giriş sayfasında olmanıza rağmen hesap verileri hala orada duruyor. +- Durum kalıcı değil, tarayıcı yenilemesi sizi giriş sayfasına geri götürüyor. +- Durumu değiştiren birden fazla fonksiyon var. Uygulama büyüdükçe, değişiklikleri takip etmek zorlaşabilir ve birini güncellemeyi unutmak kolaydır. +- Durum temizlenmiyor, bu yüzden *Çıkış Yap* düğmesine tıkladığınızda, giriş sayfasında olsanız bile hesap verileri hala orada duruyor. -Bu sorunları tek tek ele almak için kodumuzu güncelleyebiliriz, ancak bu daha fazla kod tekrarı yaratır ve uygulamayı daha karmaşık ve bakımını zor hale getirir. Ya da birkaç dakika durup stratejimizi yeniden düşünebiliriz. +Bu sorunları tek tek ele almak için kodumuzu güncelleyebiliriz, ancak bu daha fazla kod tekrarı yaratır ve uygulamayı daha karmaşık ve zor yönetilebilir hale getirir. Ya da birkaç dakika durup stratejimizi yeniden düşünebiliriz. > Burada gerçekten çözmeye çalıştığımız sorunlar nelerdir? [Durum yönetimi](https://en.wikipedia.org/wiki/State_management), bu iki özel sorunu çözmek için iyi bir yaklaşım bulmakla ilgilidir: -- Uygulamadaki veri akışlarını nasıl anlaşılır hale getirebiliriz? +- Bir uygulamadaki veri akışlarını nasıl anlaşılır hale getirebiliriz? - Durum verilerini her zaman kullanıcı arayüzüyle (ve tam tersi) nasıl senkronize tutabiliriz? -Bu sorunları çözdükten sonra, karşılaşabileceğiniz diğer sorunlar ya zaten çözülmüş olabilir ya da çözülmesi daha kolay hale gelmiştir. Bu sorunları çözmek için birçok olası yaklaşım vardır, ancak biz **verileri ve bunları değiştirme yollarını merkezileştirme** içeren yaygın bir çözümle ilerleyeceğiz. Veri akışları şu şekilde olur: +Bu sorunları çözdüğünüzde, karşılaşabileceğiniz diğer sorunlar ya zaten çözülmüş olur ya da çözülmesi daha kolay hale gelir. Bu sorunları çözmek için birçok olası yaklaşım vardır, ancak biz **verileri ve bunları değiştirme yollarını merkezileştirme** içeren yaygın bir çözümle ilerleyeceğiz. Veri akışları şu şekilde olur: ![HTML, kullanıcı eylemleri ve durum arasındaki veri akışlarını gösteren şema](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.tr.png) -> Burada verilerin otomatik olarak görünümü güncelleme kısmını ele almayacağız, çünkü bu daha ileri düzey [Reaktif Programlama](https://en.wikipedia.org/wiki/Reactive_programming) kavramlarına bağlıdır. Derinlemesine bir inceleme yapmak istiyorsanız bu iyi bir takip konusu olabilir. +> Burada verilerin otomatik olarak görünümü güncelleme kısmını ele almayacağız, çünkü bu daha ileri düzey [Reaktif Programlama](https://en.wikipedia.org/wiki/Reactive_programming) kavramlarına bağlıdır. Derinlemesine bir inceleme yapmak istiyorsanız, bu iyi bir takip konusu olabilir. ✅ Durum yönetimi için farklı yaklaşımlara sahip birçok kütüphane var, [Redux](https://redux.js.org) popüler bir seçenek. Büyük web uygulamalarında karşılaşabileceğiniz potansiyel sorunları ve bunların nasıl çözülebileceğini öğrenmek için kullanılan kavramlara ve desenlere göz atabilirsiniz. @@ -67,7 +67,7 @@ Biraz yeniden düzenleme ile başlayacağız. `account` tanımını şu şekilde let account = null; ``` -Şununla değiştirin: +Şununla: ```js let state = { @@ -75,21 +75,21 @@ let state = { }; ``` -Fikir, tüm uygulama verilerimizi tek bir durum nesnesinde *merkezileştirmek*. Şu anda durum içinde yalnızca `account` var, bu yüzden çok fazla değişiklik olmuyor, ancak evrimler için bir yol oluşturuyor. +Buradaki fikir, tüm uygulama verilerimizi tek bir durum nesnesinde *merkezileştirmek*. Şu anda durum içinde yalnızca `account` var, bu yüzden çok fazla değişiklik olmuyor, ancak gelişim için bir yol oluşturuyor. -Bunu kullanan işlevleri de güncellememiz gerekiyor. `register()` ve `login()` işlevlerinde, `account = ...` satırını `state.account = ...` ile değiştirin. +Bunu kullanan fonksiyonları da güncellememiz gerekiyor. `register()` ve `login()` fonksiyonlarında, `account = ...` ifadesini `state.account = ...` ile değiştirin. -`updateDashboard()` işlevinin başına şu satırı ekleyin: +`updateDashboard()` fonksiyonunun başına şu satırı ekleyin: ```js const account = state.account; ``` -Bu yeniden düzenleme tek başına çok fazla iyileştirme sağlamadı, ancak fikir bir sonraki değişiklikler için temel oluşturmaktı. +Bu yeniden düzenleme tek başına çok fazla iyileştirme sağlamadı, ancak sonraki değişiklikler için temel oluşturmayı amaçladı. -## Veri değişikliklerini takip etme +## Veri Değişikliklerini Takip Etmek -Artık verilerimizi depolamak için `state` nesnesini oluşturduğumuza göre, bir sonraki adım güncellemeleri merkezileştirmek. Amaç, herhangi bir değişikliği ve ne zaman gerçekleştiğini takip etmeyi kolaylaştırmaktır. +Artık verilerimizi saklamak için `state` nesnesini oluşturduğumuza göre, bir sonraki adım güncellemeleri merkezileştirmek. Amaç, herhangi bir değişikliği ve ne zaman gerçekleştiğini takip etmeyi kolaylaştırmaktır. `state` nesnesinde değişiklik yapılmasını önlemek için, onu tamamen [*değişmez*](https://en.wikipedia.org/wiki/Immutable_object) olarak düşünmek de iyi bir uygulamadır, yani hiç değiştirilemez. Bu aynı zamanda, içinde bir şey değiştirmek istiyorsanız yeni bir durum nesnesi oluşturmanız gerektiği anlamına gelir. Bunu yaparak, potansiyel olarak istenmeyen [yan etkilerden](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) korunma sağlar ve uygulamanızda geri al/yeniden yap gibi yeni özellikler uygulama olasılıklarını açar, ayrıca hata ayıklamayı kolaylaştırır. Örneğin, duruma yapılan her değişikliği kaydedebilir ve bir hatanın kaynağını anlamak için değişikliklerin geçmişini tutabilirsiniz. @@ -99,7 +99,7 @@ JavaScript'te [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScr ### Görev -Yeni bir `updateState()` işlevi oluşturalım: +Yeni bir `updateState()` fonksiyonu oluşturalım: ```js function updateState(property, newData) { @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -Bu işlevde, önceki durumdan veri kopyalayarak yeni bir durum nesnesi oluşturuyoruz. Ardından, durum nesnesinin belirli bir özelliğini yeni veriyle [köşeli parantez notasyonu](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` kullanarak geçersiz kılıyoruz. Son olarak, `Object.freeze()` kullanarak nesneyi değişikliklere karşı kilitliyoruz. Şu anda durum içinde yalnızca `account` özelliği var, ancak bu yaklaşımla duruma ihtiyaç duyduğunuz kadar çok özellik ekleyebilirsiniz. +Bu fonksiyonda, önceki durumdan veri kopyalayarak yeni bir durum nesnesi oluşturuyoruz ve ardından [köşeli parantez notasyonu](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` kullanarak durum nesnesinin belirli bir özelliğini yeni veriyle değiştiriyoruz. Son olarak, `Object.freeze()` kullanarak nesneyi değişikliklere karşı kilitliyoruz. Şu anda durum içinde yalnızca `account` özelliği saklanıyor, ancak bu yaklaşımla duruma ihtiyaç duyduğunuz kadar çok özellik ekleyebilirsiniz. -Durum başlatmasını da güncelleyeceğiz, böylece başlangıç durumu da donmuş olacak: +Durumun başlangıçta da kilitli olduğundan emin olmak için `state` başlatmasını güncelleyeceğiz: ```js let state = Object.freeze({ @@ -120,13 +120,13 @@ let state = Object.freeze({ }); ``` -Bundan sonra, `register` işlevini güncelleyerek `state.account = result;` atamasını şu şekilde değiştirin: +Bundan sonra, `register` fonksiyonunda `state.account = result;` atamasını şu şekilde değiştirin: ```js updateState('account', result); ``` -Aynı işlemi `login` işlevi için yapın, `state.account = data;` satırını şu şekilde değiştirin: +Aynı işlemi `login` fonksiyonunda yapın, `state.account = data;` ifadesini şu şekilde değiştirin: ```js updateState('account', data); @@ -134,7 +134,7 @@ updateState('account', data); Şimdi kullanıcı *Çıkış Yap* düğmesine tıkladığında hesap verilerinin temizlenmemesi sorununu düzeltme fırsatını değerlendireceğiz. -Yeni bir `logout()` işlevi oluşturun: +Yeni bir `logout()` fonksiyonu oluşturun: ```js function logout() { @@ -145,27 +145,27 @@ function logout() { `updateDashboard()` içinde, `return navigate('/login');` yönlendirmesini `return logout();` ile değiştirin. -Yeni bir hesap oluşturmayı, çıkış yapmayı ve tekrar giriş yapmayı deneyerek her şeyin hala düzgün çalıştığını kontrol edin. +Yeni bir hesap kaydetmeyi, çıkış yapmayı ve tekrar giriş yapmayı deneyin, her şeyin hala düzgün çalıştığını kontrol edin. -> İpucu: Tüm durum değişikliklerini görmek için `updateState()` işlevinin altına `console.log(state)` ekleyebilir ve tarayıcınızın geliştirme araçlarındaki konsolu açabilirsiniz. +> İpucu: Tüm durum değişikliklerini görmek için `updateState()` fonksiyonunun altına `console.log(state)` ekleyebilir ve tarayıcınızın geliştirme araçlarındaki konsolu açabilirsiniz. -## Durumu kalıcı hale getirme +## Durumu Kalıcı Hale Getirmek -Çoğu web uygulaması, doğru çalışabilmek için verileri kalıcı hale getirmeye ihtiyaç duyar. Tüm kritik veriler genellikle bir veritabanında saklanır ve bir sunucu API'si aracılığıyla erişilir, bizim durumumuzda olduğu gibi kullanıcı hesap verileri. Ancak bazen, daha iyi bir kullanıcı deneyimi veya yükleme performansını artırmak için tarayıcıda çalışan istemci uygulamasında bazı verileri kalıcı hale getirmek ilginç olabilir. +Çoğu web uygulaması, doğru çalışabilmek için verileri kalıcı hale getirmeye ihtiyaç duyar. Tüm kritik veriler genellikle bir veritabanında saklanır ve bir sunucu API'si aracılığıyla erişilir, örneğin kullanıcı hesap verileri gibi. Ancak bazen, daha iyi bir kullanıcı deneyimi veya yükleme performansını artırmak için tarayıcıda çalışan istemci uygulamasında bazı verileri kalıcı hale getirmek de ilginç olabilir. -Tarayıcınızda veri saklamak istediğinizde, kendinize sormanız gereken birkaç önemli soru vardır: +Tarayıcınızda veri kalıcı hale getirmek istediğinizde, kendinize sormanız gereken birkaç önemli soru vardır: -- *Veri hassas mı?* İstemcide kullanıcı şifreleri gibi hassas verileri saklamaktan kaçınmalısınız. +- *Veri hassas mı?* Kullanıcı şifreleri gibi hassas verileri istemcide saklamaktan kaçınmalısınız. - *Bu veriyi ne kadar süreyle saklamanız gerekiyor?* Bu veriye yalnızca mevcut oturum için mi erişmeyi planlıyorsunuz yoksa sonsuza kadar mı saklamak istiyorsunuz? -Bir web uygulamasında bilgi saklamanın, ne elde etmek istediğinize bağlı olarak birçok yolu vardır. Örneğin, bir arama sorgusunu saklamak ve bunu kullanıcılar arasında paylaşılabilir hale getirmek için URL'leri kullanabilirsiniz. Ayrıca, [kimlik doğrulama](https://en.wikipedia.org/wiki/Authentication) bilgileri gibi verilerin sunucuyla paylaşılması gerekiyorsa [HTTP çerezlerini](https://developer.mozilla.org/docs/Web/HTTP/Cookies) kullanabilirsiniz. +Bir web uygulamasında bilgi saklamanın, ne elde etmek istediğinize bağlı olarak birçok yolu vardır. Örneğin, bir arama sorgusunu saklamak için URL'leri kullanabilir ve bunu kullanıcılar arasında paylaşılabilir hale getirebilirsiniz. Ayrıca, [kimlik doğrulama](https://en.wikipedia.org/wiki/Authentication) bilgileri gibi verilerin sunucuyla paylaşılması gerekiyorsa [HTTP çerezlerini](https://developer.mozilla.org/docs/Web/HTTP/Cookies) kullanabilirsiniz. -Bir diğer seçenek, veri saklamak için birçok tarayıcı API'sinden birini kullanmaktır. İkisi özellikle ilginçtir: +Veri saklamak için birçok tarayıcı API'si vardır. İkisi özellikle ilginçtir: - [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): belirli bir web sitesine özgü verileri farklı oturumlar arasında kalıcı hale getiren bir [Anahtar/Değer deposu](https://en.wikipedia.org/wiki/Key%E2%80%93value_database). İçindeki veriler asla sona ermez. - [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): bu, `localStorage` ile aynı şekilde çalışır, ancak içinde saklanan veriler oturum sona erdiğinde (tarayıcı kapatıldığında) temizlenir. -Her iki API'nin de yalnızca [dizeleri](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) saklamaya izin verdiğini unutmayın. Karmaşık nesneleri saklamak istiyorsanız, bunu [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) kullanarak [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) formatında serileştirmeniz gerekir. +Her iki API'nin de yalnızca [string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) saklamaya izin verdiğini unutmayın. Karmaşık nesneleri saklamak istiyorsanız, bunu [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) kullanarak [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) formatında serileştirmeniz gerekir. ✅ Bir sunucuyla çalışmayan bir web uygulaması oluşturmak istiyorsanız, istemcide bir veritabanı oluşturmak için [`IndexedDB` API'sini](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) kullanmak da mümkündür. Bu, ileri düzey kullanım durumları veya önemli miktarda veri saklamanız gerektiğinde ayrılmıştır, çünkü kullanımı daha karmaşıktır. @@ -177,7 +177,7 @@ Kullanıcılarımızın *Çıkış Yap* düğmesine açıkça tıklayana kadar o const storageKey = 'savedAccount'; ``` -Ardından `updateState()` işlevinin sonuna şu satırı ekleyin: +Ardından `updateState()` fonksiyonunun sonuna şu satırı ekleyin: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); Bununla, kullanıcı hesap verileri kalıcı hale gelecek ve daha önce tüm durum güncellemelerini merkezileştirdiğimiz için her zaman güncel olacak. İşte önceki yeniden düzenlemelerimizin faydalarını görmeye başladığımız yer 🙂. -Veriler kaydedildiği için, uygulama yüklendiğinde bunları geri yüklemekle de ilgilenmemiz gerekiyor. Daha fazla başlatma koduna sahip olmaya başlayacağımız için, `app.js` dosyasının altındaki önceki kodumuzu da içeren yeni bir `init` işlevi oluşturmak iyi bir fikir olabilir: +Veriler kaydedildiği için, uygulama yüklendiğinde bunları geri yüklemekle de ilgilenmemiz gerekiyor. Daha fazla başlatma koduna sahip olmaya başlayacağımız için, `app.js` dosyasının altındaki önceki kodumuzu da içeren yeni bir `init` fonksiyonu oluşturmak iyi bir fikir olabilir: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -Burada kaydedilen verileri alıyoruz ve herhangi bir veri varsa durumu buna göre güncelliyoruz. Bunu *sayfayı güncelleme* sırasında duruma güvenen kod olabileceğinden, rotayı güncellemeden *önce* yapmak önemlidir. +Burada kaydedilen verileri alıyoruz ve varsa durumu buna göre güncelliyoruz. Bunu *sayfayı güncellemeden önce* yapmak önemlidir, çünkü sayfa güncellemesi sırasında duruma güvenen kodlar olabilir. -Artık *Dashboard* sayfasını uygulamamızın varsayılan sayfası yapabiliriz, çünkü artık hesap verilerini kalıcı hale getiriyoruz. Herhangi bir veri bulunmazsa, dashboard zaten *Giriş* sayfasına yönlendirme işlemini gerçekleştiriyor. `updateRoute()` içinde, geri dönüş `return navigate('/login');` satırını `return navigate('/dashboard');` ile değiştirin. +Artık hesap verilerini kalıcı hale getirdiğimiz için *Dashboard* sayfasını uygulamamızın varsayılan sayfası yapabiliriz. Eğer veri bulunmazsa, dashboard zaten *Giriş* sayfasına yönlendirme işlemini gerçekleştiriyor. `updateRoute()` içinde, geri dönüş `return navigate('/login');` ifadesini `return navigate('/dashboard');` ile değiştirin. Şimdi uygulamada oturum açın ve sayfayı yenilemeyi deneyin. Dashboard'da kalmalısınız. Bu güncelleme ile tüm başlangıç sorunlarımızı ele aldık... -## Verileri yenileme +## Verileri Yenilemek ...Ama aynı zamanda yeni bir sorun yaratmış olabiliriz. Oops! -`test` hesabını kullanarak dashboard'a gidin, ardından bir terminalde yeni bir işlem oluşturmak için şu komutu çalıştırın: +`test` hesabını kullanarak dashboard'a gidin, ardından bir terminalde şu komutu çalıştırarak yeni bir işlem oluşturun: ```sh curl --request POST \ @@ -223,13 +223,13 @@ curl --request POST \ Şimdi tarayıcıdaki dashboard sayfasını yenilemeyi deneyin. Ne oluyor? Yeni işlemi görüyor musunuz? -Durum, `localStorage` sayesinde süresiz olarak kalıcı hale geliyor, ancak bu aynı zamanda, uygulamadan çıkış yapıp tekrar giriş yapana kadar hiç güncellenmediği anlamına geliyor! +Durum `localStorage` sayesinde süresiz olarak kalıcı hale geldi, ancak bu aynı zamanda uygulamadan çıkış yapıp tekrar giriş yapana kadar hiç güncellenmediği anlamına geliyor! Bunu düzeltmek için olası bir strateji, dashboard her yüklendiğinde hesap verilerini yeniden yüklemek olabilir, böylece eski verilerden kaçınılır. ### Görev -Yeni bir `updateAccountData` işlevi oluşturun: +Yeni bir `updateAccountData` fonksiyonu oluşturun: ```js async function updateAccountData() { @@ -249,7 +249,7 @@ async function updateAccountData() { Bu yöntem, şu anda oturum açmış olduğumuzu kontrol eder ve ardından hesap verilerini sunucudan yeniden yükler. -`refresh` adında başka bir işlev oluşturun: +`refresh` adında başka bir fonksiyon oluşturun: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -Bu işlev hesap verilerini günceller ve ardından dashboard sayfasının HTML'ini günceller. Dashboard rotası yüklendiğinde çağırmamız gereken şey budur. Rota tanımını şu şekilde güncelleyin: +Bu, hesap verilerini günceller ve ardından dashboard sayfasının HTML'sini günceller. Dashboard rotası yüklendiğinde çağırmamız gereken şey budur. Rota tanımını şu şekilde güncelleyin: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -Şimdi dashboard'u yenilemeyi deneyin, güncellenmiş hesap verilerini göstermesi gerekiyor. +Şimdi dashboard'u yenilemeyi deneyin, güncellenmiş hesap verilerini göstermesi gerekir. --- ## 🚀 Zorluk -Dashboard her yüklendiğinde hesap verilerini yeniden yüklediğimize göre, sizce *tüm hesap* verilerini kalıcı hale getirmemiz hala gerekli mi? +Artık dashboard her yüklendiğinde hesap verilerini yeniden yüklüyoruz, sizce *tüm hesap* verilerini kalıcı hale getirmemiz hala gerekli mi? -Birlikte çalışarak `localStorage` içinde yalnızca uygulamanın çalışması için kesinlikle gerekli olan verileri saklayacak ve yükleyecek şekilde değişiklik yapmayı deneyin. +Birlikte çalışarak `localStorage`'da saklanan ve yüklenen verileri yalnızca uygulamanın çalışması için kesinlikle gerekli olanlarla sınırlamayı deneyin. ## Ders Sonrası Test - -[Ders sonrası test](https://ff-quizzes.netlify.app/web/quiz/48) +[Post-lecture quiz](https://ff-quizzes.netlify.app/web/quiz/48) ## Ödev -[İşlem ekleme" iletişim kutusunu uygula](assignment.md) -İşte görevi tamamladıktan sonra elde edilen örnek bir sonuç: +["İşlem ekle" diyalog kutusunu uygulayın](assignment.md) + +Ödevi tamamladıktan sonra ortaya çıkan örnek sonuç aşağıda gösterilmiştir: -![Bir örnek "İşlem ekleme" iletişim kutusunu gösteren ekran görüntüsü](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.tr.png) +!["İşlem ekle" diyalog kutusunun örnek ekran görüntüsü](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.tr.png) --- **Feragatname**: -Bu belge, AI çeviri hizmeti [Co-op Translator](https://github.com/Azure/co-op-translator) kullanılarak çevrilmiştir. Doğruluk için çaba göstersek de, otomatik çevirilerin hata veya yanlışlıklar içerebileceğini lütfen unutmayın. Belgenin orijinal dili, yetkili kaynak olarak kabul edilmelidir. Kritik bilgiler için profesyonel insan çevirisi önerilir. Bu çevirinin kullanımından kaynaklanan yanlış anlamalar veya yanlış yorumlamalardan sorumlu değiliz. \ No newline at end of file +Bu belge, AI çeviri hizmeti [Co-op Translator](https://github.com/Azure/co-op-translator) kullanılarak çevrilmiştir. Doğruluk için çaba göstersek de, otomatik çevirilerin hata veya yanlışlıklar içerebileceğini lütfen unutmayın. Belgenin orijinal dili, yetkili kaynak olarak kabul edilmelidir. Kritik bilgiler için profesyonel insan çevirisi önerilir. Bu çevirinin kullanımından kaynaklanan yanlış anlamalar veya yanlış yorumlamalar için sorumluluk kabul etmiyoruz. \ No newline at end of file diff --git a/translations/tw/7-bank-project/4-state-management/README.md b/translations/tw/7-bank-project/4-state-management/README.md index be44a8d01..4ed4e1e31 100644 --- a/translations/tw/7-bank-project/4-state-management/README.md +++ b/translations/tw/7-bank-project/4-state-management/README.md @@ -1,29 +1,29 @@ -# 建立銀行應用程式第 4 部分:狀態管理的概念 +# 建立銀行應用程式第4部分:狀態管理概念 ## 課前測驗 [課前測驗](https://ff-quizzes.netlify.app/web/quiz/47) -### 介紹 +### 簡介 -隨著網頁應用程式的規模增長,追蹤所有數據流變得越來越具有挑戰性。哪些程式碼獲取了數據,哪些頁面使用了數據,數據需要在何時何地更新……很容易導致程式碼變得混亂且難以維護。當需要在應用程式的不同頁面之間共享數據時(例如用戶數據),這種情況尤其明顯。*狀態管理* 的概念一直存在於各類程式中,但隨著網頁應用程式的複雜性不斷增加,狀態管理已成為開發過程中的關鍵考量點。 +隨著網頁應用程式的規模增大,追蹤所有資料流變得越來越困難。哪些程式碼獲取資料、哪些頁面使用資料、資料需要在何時何地更新……很容易導致程式碼混亂且難以維護。尤其是當需要在應用程式的不同頁面之間共享資料時,例如使用者資料。*狀態管理*的概念一直存在於各類程式中,但隨著網頁應用程式的複雜性不斷增加,狀態管理現在已成為開發過程中的關鍵點。 -在這最後一部分,我們將重新審視我們建立的應用程式,重新思考如何管理狀態,以支持在任何時候刷新瀏覽器,並在用戶會話之間持續保存數據。 +在這最後一部分,我們將重新審視我們建立的應用程式,重新思考如何管理狀態,支持瀏覽器在任何時候刷新,並在使用者會話之間持續保存資料。 ### 前置條件 -您需要完成本課程中網頁應用程式的[數據獲取](../3-data/README.md)部分。此外,您還需要安裝 [Node.js](https://nodejs.org) 並[本地運行伺服器 API](../api/README.md),以便管理帳戶數據。 +您需要完成本課程的[資料擷取](../3-data/README.md)部分。此外,您需要安裝 [Node.js](https://nodejs.org) 並[在本地運行伺服器 API](../api/README.md),以便管理帳戶資料。 -您可以通過在終端中執行以下命令來測試伺服器是否正常運行: +您可以通過在終端執行以下命令來測試伺服器是否正常運行: ```sh curl http://localhost:5000/api @@ -34,34 +34,34 @@ curl http://localhost:5000/api ## 重新思考狀態管理 -在[上一課](../3-data/README.md)中,我們在應用程式中引入了一個基本的狀態概念,即全域變數 `account`,它包含當前登錄用戶的銀行數據。然而,我們目前的實現存在一些缺陷。嘗試在儀表板頁面刷新頁面。會發生什麼? +在[上一課程](../3-data/README.md)中,我們在應用程式中引入了基本的狀態概念,使用全域變數 `account` 來保存當前登入使用者的銀行資料。然而,我們目前的實現存在一些缺陷。嘗試在儀表板頁面刷新瀏覽器。會發生什麼? -目前的程式碼存在三個問題: +目前程式碼有三個問題: -- 狀態未被持久化,刷新瀏覽器會將您帶回登錄頁面。 -- 有多個函數修改狀態。隨著應用程式的增長,這可能使得追蹤更改變得困難,並且很容易忘記更新某些部分。 -- 狀態未被清理,因此當您點擊 *登出* 時,即使您已經在登錄頁面,帳戶數據仍然存在。 +- 狀態未持久化,瀏覽器刷新後會返回登入頁面。 +- 有多個函數修改狀態。隨著應用程式的增長,這可能使追蹤變更變得困難,並且容易忘記更新某些部分。 +- 狀態未清理,因此當您點擊*登出*時,帳戶資料仍然存在,即使您已經回到登入頁面。 -我們可以逐一更新程式碼來解決這些問題,但這會導致程式碼重複,並使應用程式更加複雜且難以維護。或者,我們可以暫停幾分鐘,重新思考我們的策略。 +我們可以逐一更新程式碼來解決這些問題,但這會導致程式碼重複並使應用程式更加複雜且難以維護。或者,我們可以花幾分鐘重新思考策略。 -> 我們真正想要解決的問題是什麼? +> 我們真正試圖解決的問題是什麼? -[狀態管理](https://en.wikipedia.org/wiki/State_management) 的核心在於找到一種良好的方法來解決以下兩個特定問題: +[狀態管理](https://en.wikipedia.org/wiki/State_management)的核心在於找到一個良好的方法來解決以下兩個特定問題: -- 如何讓應用程式中的數據流保持清晰易懂? -- 如何確保狀態數據始終與用戶界面保持同步(反之亦然)? +- 如何使應用程式中的資料流易於理解? +- 如何確保狀態資料始終與使用者介面保持同步(反之亦然)? -一旦解決了這些問題,您可能已經解決了其他問題,或者使它們變得更容易解決。解決這些問題有許多可能的方法,但我們將採用一種常見的解決方案,即**集中化數據及其更改方式**。數據流將如下所示: +一旦解決了這些問題,您可能已經解決了其他問題,或者使它們更容易解決。有許多方法可以解決這些問題,但我們將採用一種常見的解決方案,即**集中化資料及其變更方式**。資料流將如下所示: -![顯示 HTML、用戶操作和狀態之間數據流的圖表](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.tw.png) +![顯示 HTML、使用者操作和狀態之間資料流的架構圖](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.tw.png) -> 我們在此不會涵蓋數據自動觸發視圖更新的部分,因為這涉及到更高級的[反應式編程](https://en.wikipedia.org/wiki/Reactive_programming)概念。如果您有興趣深入研究,這是一個不錯的後續主題。 +> 我們在此不會涵蓋資料自動觸發視圖更新的部分,因為這涉及到更高級的[反應式程式設計](https://en.wikipedia.org/wiki/Reactive_programming)概念。如果您有興趣深入研究,這是一個很好的後續主題。 -✅ 市面上有許多不同方法的狀態管理庫,[Redux](https://redux.js.org) 是一個流行的選擇。了解其使用的概念和模式通常是學習如何解決大型網頁應用程式中潛在問題的好方法。 +✅ 市面上有許多不同方法的狀態管理庫,[Redux](https://redux.js.org) 是一個受歡迎的選擇。了解其概念和模式通常是學習大型網頁應用程式可能面臨的潛在問題以及如何解決這些問題的好方法。 ### 任務 -我們將從一些重構開始。將 `account` 聲明替換為: +我們將從一些重構開始。替換 `account` 宣告: ```js let account = null; @@ -75,27 +75,27 @@ let state = { }; ``` -這樣做的目的是將我們應用程式的所有數據集中到一個單一的狀態物件中。目前狀態中只有 `account`,因此變化不大,但這為未來的擴展奠定了基礎。 +這個想法是將我們的應用程式資料*集中化*到一個單一的狀態物件中。目前狀態中只有 `account`,因此變化不大,但這為未來的擴展奠定了基礎。 我們還需要更新使用它的函數。在 `register()` 和 `login()` 函數中,將 `account = ...` 替換為 `state.account = ...`; -在 `updateDashboard()` 函數的開頭,添加以下程式碼: +在 `updateDashboard()` 函數的頂部,添加以下行: ```js const account = state.account; ``` -這次重構本身並未帶來太多改進,但目的是為接下來的更改奠定基礎。 +這次重構本身並未帶來太多改進,但其目的是為接下來的變更奠定基礎。 -## 追蹤數據變更 +## 追蹤資料變更 -現在我們已經設置了 `state` 物件來存儲數據,下一步是集中更新。目標是更容易追蹤任何變更及其發生的時間。 +現在我們已經設置了 `state` 物件來存儲資料,下一步是集中更新。目標是使追蹤任何變更及其發生時間變得更容易。 -為了避免對 `state` 物件進行直接更改,將其視為[*不可變*](https://en.wikipedia.org/wiki/Immutable_object)是一個好習慣,這意味著它完全不能被修改。這也意味著如果您想更改其中的任何內容,必須創建一個新的狀態物件。這樣做可以防止潛在的[副作用](https://en.wikipedia.org/wiki/Side_effect_(computer_science)),並為應用程式的新功能(如實現撤銷/重做)提供可能性,同時也更容易進行調試。例如,您可以記錄對狀態所做的每次更改,並保留更改歷史記錄,以便了解錯誤的來源。 +為了避免對 `state` 物件進行更改,考慮將其視為[*不可變*](https://en.wikipedia.org/wiki/Immutable_object)是一個良好的做法,這意味著它完全不能被修改。這也意味著如果您想更改其中的任何內容,必須創建一個新的狀態物件。通過這樣做,您可以防止潛在的[副作用](https://en.wikipedia.org/wiki/Side_effect_(computer_science)),並為應用程式的新功能(例如實現撤銷/重做)打開可能性,同時也使調試更容易。例如,您可以記錄對狀態所做的每次更改,並保留更改的歷史記錄,以了解錯誤的來源。 在 JavaScript 中,您可以使用 [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) 創建物件的不可變版本。如果嘗試更改不可變物件,將引發異常。 -✅ 您知道 *淺不可變* 和 *深不可變* 物件之間的區別嗎?您可以在[這裡](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze)閱讀相關內容。 +✅ 您知道*淺層*和*深層*不可變物件的區別嗎?您可以在[這裡](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze)閱讀相關內容。 ### 任務 @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -在這個函數中,我們創建了一個新的狀態物件,並使用[*展開運算符 (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals)從先前的狀態中複製數據。然後,我們使用[方括號表示法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` 覆蓋狀態物件中的特定屬性。最後,我們使用 `Object.freeze()` 鎖定物件以防止修改。目前狀態中僅存儲了 `account` 屬性,但通過這種方法,您可以在狀態中添加任意多的屬性。 +在此函數中,我們創建了一個新的狀態物件,並使用[*展開運算符 (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals)從先前的狀態中複製資料。然後,我們使用[方括號表示法](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` 覆蓋狀態物件的特定屬性。最後,我們使用 `Object.freeze()` 鎖定物件以防止修改。目前狀態中僅存儲 `account` 屬性,但使用此方法,您可以在狀態中添加任意多的屬性。 我們還需要更新 `state` 的初始化,以確保初始狀態也是不可變的: @@ -120,21 +120,21 @@ let state = Object.freeze({ }); ``` -接下來,更新 `register` 函數,將 `state.account = result;` 替換為: +之後,更新 `register` 函數,將 `state.account = result;` 替換為: ```js updateState('account', result); ``` -對 `login` 函數執行相同操作,將 `state.account = data;` 替換為: +對 `login` 函數進行相同的更新,將 `state.account = data;` 替換為: ```js updateState('account', data); ``` -我們現在可以趁機修復用戶點擊 *登出* 時帳戶數據未被清除的問題。 +現在我們可以順便修復使用者點擊*登出*時帳戶資料未清除的問題。 -創建一個新函數 `logout()`: +創建一個新的函數 `logout()`: ```js function logout() { @@ -143,49 +143,49 @@ function logout() { } ``` -在 `updateDashboard()` 中,將重定向 `return navigate('/login');` 替換為 `return logout();` +在 `updateDashboard()` 中,將重定向 `return navigate('/login');` 替換為 `return logout()`; -嘗試註冊一個新帳戶,登出並重新登錄,檢查一切是否仍然正常運作。 +嘗試註冊新帳戶,登出並再次登入,檢查是否一切正常。 -> 提示:您可以通過在 `updateState()` 的底部添加 `console.log(state)`,並打開瀏覽器開發工具中的控制台,來查看所有狀態變更。 +> 提示:您可以通過在 `updateState()` 的底部添加 `console.log(state)` 並打開瀏覽器開發工具中的控制台來查看所有狀態變更。 ## 持久化狀態 -大多數網頁應用程式需要持久化數據才能正常運作。所有關鍵數據通常存儲在數據庫中,並通過伺服器 API 訪問,例如我們的用戶帳戶數據。但有時,將一些數據存儲在瀏覽器中運行的客戶端應用程式中也是有意義的,這樣可以提升用戶體驗或改善加載性能。 +大多數網頁應用程式需要持久化資料才能正常工作。所有關鍵資料通常存儲在資料庫中,並通過伺服器 API 訪問,例如我們的使用者帳戶資料。但有時,將某些資料存儲在瀏覽器中的客戶端應用程式中也是有益的,這可以改善使用者體驗或提高加載性能。 -當您想在瀏覽器中持久化數據時,有幾個重要問題需要考慮: +當您想在瀏覽器中持久化資料時,有幾個重要問題需要問自己: -- *數據是否敏感?* 您應避免在客戶端存儲任何敏感數據,例如用戶密碼。 -- *您需要保存這些數據多久?* 您是僅計劃在當前會話中訪問這些數據,還是希望永久保存? +- *資料是否敏感?* 您應避免在客戶端存儲任何敏感資料,例如使用者密碼。 +- *您需要保存這些資料多久?* 您是僅在當前會話中訪問這些資料,還是希望永久保存? -根據您的需求,有多種方式可以在網頁應用程式中存儲信息。例如,您可以使用 URL 存儲搜索查詢,並使其可在用戶之間共享。您還可以使用 [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) 存儲需要與伺服器共享的數據,例如[身份驗證](https://en.wikipedia.org/wiki/Authentication)信息。 +根據您的需求,有多種方法可以在網頁應用程式中存儲資訊。例如,您可以使用 URL 存儲搜尋查詢,並使其可在使用者之間共享。您還可以使用 [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) 如果需要與伺服器共享資料,例如[身份驗證](https://en.wikipedia.org/wiki/Authentication)資訊。 -另一個選擇是使用瀏覽器提供的多種 API 之一來存儲數據。其中兩個特別值得關注: +另一個選擇是使用瀏覽器提供的多種 API 來存儲資料。其中有兩個特別值得注意: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):一種[鍵值存儲](https://en.wikipedia.org/wiki/Key%E2%80%93value_database),允許跨不同會話持久化特定於當前網站的數據。存儲在其中的數據永不過期。 -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):其工作方式與 `localStorage` 相同,但存儲在其中的數據會在會話結束時(瀏覽器關閉時)被清除。 +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage):一個[鍵值存儲](https://en.wikipedia.org/wiki/Key%E2%80%93value_database),允許跨不同會話持久化特定於當前網站的資料。存儲在其中的資料永不過期。 +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage):其工作方式與 `localStorage` 相同,但存儲的資料在會話結束(瀏覽器關閉時)後會被清除。 -請注意,這兩個 API 僅允許存儲[字串](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) 格式。 +請注意,這兩個 API 只允許存儲[字串](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) 在客戶端創建數據庫。這適用於需要存儲大量數據的高級用例,因為它的使用更為複雜。 +✅ 如果您想創建一個不依賴伺服器的網頁應用程式,也可以使用 [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API) 在客戶端創建資料庫。這適用於高級用例或需要存儲大量資料的情況,因為它使用起來更為複雜。 ### 任務 -我們希望用戶在明確點擊 *登出* 按鈕之前保持登錄狀態,因此我們將使用 `localStorage` 存儲帳戶數據。首先,定義一個用於存儲數據的鍵。 +我們希望使用者在明確點擊*登出*按鈕之前保持登入狀態,因此我們將使用 `localStorage` 存儲帳戶資料。首先,定義一個用於存儲資料的鍵。 ```js const storageKey = 'savedAccount'; ``` -然後在 `updateState()` 函數的末尾添加以下程式碼: +然後在 `updateState()` 函數的末尾添加以下行: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -通過這樣做,用戶帳戶數據將被持久化,並且由於我們之前集中化了所有狀態更新,因此數據始終是最新的。這正是我們之前重構開始帶來的好處 🙂。 +有了這個,使用者帳戶資料將被持久化並始終保持最新,因為我們之前已集中化所有狀態更新。這就是我們開始從之前的重構中受益的地方 🙂。 -由於數據已保存,我們還需要在應用程式加載時恢復它。由於我們即將有更多初始化程式碼,因此最好創建一個新的 `init` 函數,將之前在 `app.js` 底部的程式碼也包含進來: +由於資料已保存,我們還需要在應用程式加載時恢復它。由於我們將開始擁有更多初始化程式碼,創建一個新的 `init` 函數可能是一個好主意,並將其包括在 `app.js` 的底部: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -在這裡,我們檢索保存的數據,如果有數據,則相應地更新狀態。重要的是在更新路由*之前*執行此操作,因為在頁面更新期間可能有程式碼依賴於狀態。 +在這裡,我們檢索保存的資料,如果有任何資料,我們相應地更新狀態。重要的是在更新路由*之前*執行此操作,因為在頁面更新期間可能有程式碼依賴於狀態。 -我們還可以將 *儀表板* 頁設為應用程式的默認頁面,因為我們現在已經持久化了帳戶數據。如果未找到數據,儀表板會負責重定向到 *登錄* 頁。在 `updateRoute()` 中,將回退 `return navigate('/login');` 替換為 `return navigate('/dashboard');`。 +我們還可以將*儀表板*頁面設為應用程式的預設頁面,因為我們現在正在持久化帳戶資料。如果未找到任何資料,儀表板會負責重定向到*登入*頁面。在 `updateRoute()` 中,將回退 `return navigate('/login');` 替換為 `return navigate('/dashboard');`。 -現在登錄應用程式並嘗試刷新頁面。您應該仍然停留在儀表板頁面。通過這次更新,我們解決了所有初始問題…… +現在登入應用程式並嘗試刷新頁面。您應該停留在儀表板上。通過這次更新,我們已解決所有初始問題... -## 刷新數據 +## 刷新資料 -……但我們可能也創造了一個新問題。糟糕! +...但我們可能也創造了一個新問題。糟糕! -使用 `test` 帳戶進入儀表板,然後在終端中運行以下命令以創建一個新交易: +使用 `test` 帳戶進入儀表板,然後在終端執行以下命令以創建新交易: ```sh curl --request POST \ @@ -221,15 +221,15 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -現在嘗試刷新瀏覽器中的儀表板頁面。會發生什麼?您是否看到新的交易? +現在嘗試在瀏覽器中刷新儀表板頁面。會發生什麼?您是否看到新交易? -由於 `localStorage` 的狀態被無限期持久化,這也意味著在您登出應用程式並重新登錄之前,它永遠不會更新! +由於 `localStorage`,狀態被無限期持久化,但這也意味著在您登出應用程式並再次登入之前,它永遠不會更新! -解決這個問題的一種策略是每次加載儀表板時重新加載帳戶數據,以避免數據陳舊。 +解決此問題的一種策略是每次加載儀表板時重新載入帳戶資料,以避免資料過時。 ### 任務 -創建一個新函數 `updateAccountData`: +創建一個新的函數 `updateAccountData`: ```js async function updateAccountData() { @@ -247,9 +247,9 @@ async function updateAccountData() { } ``` -此方法檢查我們當前是否已登錄,然後從伺服器重新加載帳戶數據。 +此方法檢查我們當前是否已登入,然後從伺服器重新載入帳戶資料。 -再創建另一個名為 `refresh` 的函數: +創建另一個名為 `refresh` 的函數: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -此函數更新帳戶數據,然後負責更新儀表板頁面的 HTML。這是我們需要在加載儀表板路由時調用的函數。使用以下程式碼更新路由定義: +此函數更新帳戶資料,然後負責更新儀表板頁面的 HTML。這是我們需要在加載儀表板路由時調用的函數。使用以下程式碼更新路由定義: ```js const routes = { @@ -267,28 +267,28 @@ const routes = { }; ``` -現在嘗試重新加載儀表板,它應該顯示更新的帳戶數據。 +現在嘗試刷新儀表板,它應顯示更新的帳戶資料。 --- ## 🚀 挑戰 -現在我們每次加載儀表板時都會重新加載帳戶數據,您認為我們是否仍然需要持久化*所有帳戶*數據? +現在我們每次加載儀表板時都重新載入帳戶資料,您認為我們是否仍需要持久化*所有帳戶*資料? -嘗試與團隊合作,修改 `localStorage` 中保存和加載的內容,使其僅包含應用程式正常運作所需的數據。 +嘗試合作更改 `localStorage` 中保存和加載的內容,只包括應用程式正常運行所需的絕對必要資料。 ## 課後測驗 - [課後測驗](https://ff-quizzes.netlify.app/web/quiz/48) ## 作業 + [實作「新增交易」對話框](assignment.md) -以下是完成任務後的範例結果: +以下是完成作業後的範例結果: -![顯示「新增交易」對話框範例的截圖](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.tw.png) +![螢幕截圖顯示範例「新增交易」對話框](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.tw.png) --- **免責聲明**: -本文件使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。我們致力於提供準確的翻譯,但請注意,自動翻譯可能包含錯誤或不準確之處。應以原始語言的文件作為權威來源。對於關鍵資訊,建議尋求專業人工翻譯。我們對因使用此翻譯而產生的任何誤解或錯誤解讀概不負責。 \ No newline at end of file +本文件已使用 AI 翻譯服務 [Co-op Translator](https://github.com/Azure/co-op-translator) 進行翻譯。儘管我們努力確保翻譯的準確性,但請注意,自動翻譯可能包含錯誤或不準確之處。原始文件的母語版本應被視為權威來源。對於關鍵信息,建議使用專業人工翻譯。我們對因使用此翻譯而引起的任何誤解或誤釋不承擔責任。 \ No newline at end of file diff --git a/translations/uk/7-bank-project/4-state-management/README.md b/translations/uk/7-bank-project/4-state-management/README.md index 032584289..5ce679b08 100644 --- a/translations/uk/7-bank-project/4-state-management/README.md +++ b/translations/uk/7-bank-project/4-state-management/README.md @@ -1,27 +1,27 @@ -# Створення банківського додатку, частина 4: Концепції управління станом +# Створення банківського додатка, частина 4: Концепції управління станом -## Попереднє опитування +## Передлекційна вікторина -[Попереднє опитування](https://ff-quizzes.netlify.app/web/quiz/47) +[Передлекційна вікторина](https://ff-quizzes.netlify.app/web/quiz/47) ### Вступ -Зі зростанням веб-додатку стає складно відстежувати всі потоки даних. Який код отримує дані, яка сторінка їх використовує, де і коли їх потрібно оновлювати... Легко опинитися з заплутаним кодом, який важко підтримувати. Це особливо актуально, коли потрібно ділитися даними між різними сторінками додатку, наприклад, даними користувача. Концепція *управління станом* завжди існувала у всіх типах програм, але з ростом складності веб-додатків це стало ключовим моментом, який варто враховувати під час розробки. +Зі зростанням веб-додатка стає складніше відстежувати всі потоки даних. Який код отримує дані, яка сторінка їх використовує, де і коли їх потрібно оновлювати... Легко опинитися з заплутаним кодом, який важко підтримувати. Це особливо актуально, коли потрібно ділитися даними між різними сторінками додатка, наприклад, даними користувача. Концепція *управління станом* завжди існувала у всіх типах програм, але зі зростанням складності веб-додатків це стало ключовим моментом, який варто враховувати під час розробки. У цій фінальній частині ми переглянемо додаток, який ми створили, щоб переосмислити, як управляється стан, забезпечуючи підтримку оновлення браузера в будь-який момент і збереження даних між сеансами користувача. ### Передумови -Вам потрібно завершити [отримання даних](../3-data/README.md) у веб-додатку для цього уроку. Також необхідно встановити [Node.js](https://nodejs.org) і [запустити сервер API](../api/README.md) локально, щоб ви могли управляти даними облікового запису. +Вам потрібно завершити частину [отримання даних](../3-data/README.md) веб-додатка для цього уроку. Також необхідно встановити [Node.js](https://nodejs.org) і [запустити сервер API](../api/README.md) локально, щоб ви могли керувати даними облікового запису. Ви можете перевірити, чи сервер працює належним чином, виконавши цю команду в терміналі: @@ -34,30 +34,30 @@ curl http://localhost:5000/api ## Переосмислення управління станом -У [попередньому уроці](../3-data/README.md) ми ввели базову концепцію стану в нашому додатку за допомогою глобальної змінної `account`, яка містить банківські дані для поточного користувача, що увійшов у систему. Однак наша поточна реалізація має деякі недоліки. Спробуйте оновити сторінку, коли ви перебуваєте на інформаційній панелі. Що відбувається? +У [попередньому уроці](../3-data/README.md) ми ввели базове поняття стану в нашому додатку за допомогою глобальної змінної `account`, яка містить банківські дані для поточного користувача. Однак наша поточна реалізація має деякі недоліки. Спробуйте оновити сторінку, коли ви на інформаційній панелі. Що відбувається? Є три проблеми з поточним кодом: - Стан не зберігається, оскільки оновлення браузера повертає вас на сторінку входу. -- Є кілька функцій, які змінюють стан. Зі зростанням додатку це може ускладнити відстеження змін, і легко забути оновити одну з них. -- Стан не очищається, тому коли ви натискаєте *Вийти*, дані облікового запису все ще залишаються, навіть якщо ви перебуваєте на сторінці входу. +- Є кілька функцій, які змінюють стан. У міру зростання додатка це може ускладнити відстеження змін, і легко забути оновити одну з них. +- Стан не очищається, тому коли ви натискаєте *Вийти*, дані облікового запису все ще залишаються, навіть якщо ви на сторінці входу. -Ми могли б оновити наш код, щоб вирішити ці проблеми по одному, але це створило б більше дублювання коду і зробило додаток більш складним і важким для підтримки. Або ми могли б зупинитися на кілька хвилин і переосмислити нашу стратегію. +Ми могли б оновити наш код, щоб вирішити ці проблеми по одному, але це створило б більше дублювання коду і зробило б додаток складнішим для підтримки. Або ми могли б зупинитися на кілька хвилин і переосмислити нашу стратегію. > Які проблеми ми насправді намагаємося вирішити? -[Управління станом](https://en.wikipedia.org/wiki/State_management) полягає у знаходженні хорошого підходу для вирішення цих двох конкретних проблем: +[Управління станом](https://uk.wikipedia.org/wiki/Управління_станом) полягає у знаходженні хорошого підходу для вирішення цих двох конкретних проблем: - Як зробити потоки даних у додатку зрозумілими? -- Як забезпечити синхронізацію даних стану з інтерфейсом користувача (і навпаки)? +- Як забезпечити, щоб дані стану завжди були синхронізовані з інтерфейсом користувача (і навпаки)? -Як тільки ви вирішите ці проблеми, будь-які інші проблеми, які можуть виникнути, або вже будуть вирішені, або стануть легшими для вирішення. Існує багато можливих підходів для вирішення цих проблем, але ми оберемо загальне рішення, яке полягає у **централізації даних і способів їх зміни**. Потоки даних виглядатимуть так: +Як тільки ви вирішите ці питання, будь-які інші проблеми, які можуть виникнути, або вже будуть вирішені, або стануть легшими для вирішення. Є багато можливих підходів для вирішення цих проблем, але ми оберемо поширене рішення, яке полягає у **централізації даних і способів їх зміни**. Потоки даних виглядатимуть так: -![Схема, що показує потоки даних між HTML, діями користувача і станом](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.uk.png) +![Схема, що показує потоки даних між HTML, діями користувача та станом](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.uk.png) -> Тут ми не будемо розглядати частину, де дані автоматично викликають оновлення представлення, оскільки це пов'язано з більш складними концепціями [Реактивного програмування](https://en.wikipedia.org/wiki/Reactive_programming). Це хороший предмет для подальшого вивчення, якщо ви готові до глибокого занурення. +> Ми не будемо тут розглядати частину, де дані автоматично оновлюють вигляд, оскільки це пов'язано з більш складними концепціями [Реактивного програмування](https://uk.wikipedia.org/wiki/Реактивне_програмування). Це гарна тема для подальшого вивчення, якщо ви готові до глибшого занурення. -✅ Існує багато бібліотек з різними підходами до управління станом, [Redux](https://redux.js.org) є популярним варіантом. Ознайомтеся з концепціями і шаблонами, які використовуються, оскільки це часто хороший спосіб дізнатися, з якими потенційними проблемами ви можете зіткнутися у великих веб-додатках і як їх можна вирішити. +✅ Існує багато бібліотек з різними підходами до управління станом, [Redux](https://redux.js.org) є популярним варіантом. Ознайомтеся з концепціями та шаблонами, які використовуються, оскільки це часто хороший спосіб дізнатися, з якими потенційними проблемами ви можете зіткнутися у великих веб-додатках і як їх можна вирішити. ### Завдання @@ -75,7 +75,7 @@ let state = { }; ``` -Ідея полягає у *централізації* всіх даних нашого додатку в одному об'єкті стану. Зараз у стані є лише `account`, тому це не сильно змінює ситуацію, але створює основу для подальших змін. +Ідея полягає в тому, щоб *централізувати* всі дані нашого додатка в одному об'єкті стану. Зараз у нас є лише `account` у стані, тому це не змінює багато, але створює основу для подальших змін. Також потрібно оновити функції, які його використовують. У функціях `register()` і `login()` замініть `account = ...` на `state.account = ...`; @@ -85,15 +85,15 @@ let state = { const account = state.account; ``` -Цей рефакторинг сам по собі не приніс значних покращень, але ідея полягала у створенні основи для наступних змін. +Цей рефакторинг сам по собі не приніс великих покращень, але ідея полягала в тому, щоб закласти основу для наступних змін. ## Відстеження змін даних -Тепер, коли ми створили об'єкт `state` для зберігання наших даних, наступним кроком є централізація оновлень. Мета полягає у тому, щоб зробити легшим відстеження будь-яких змін і моментів, коли вони відбуваються. +Тепер, коли ми створили об'єкт `state` для зберігання наших даних, наступним кроком є централізація оновлень. Мета полягає в тому, щоб полегшити відстеження будь-яких змін і моментів, коли вони відбуваються. -Щоб уникнути змін у об'єкті `state`, також хорошою практикою є вважати його [*незмінним*](https://en.wikipedia.org/wiki/Immutable_object), тобто таким, який взагалі не можна змінювати. Це також означає, що вам потрібно створити новий об'єкт стану, якщо ви хочете щось у ньому змінити. Роблячи це, ви створюєте захист від потенційно небажаних [побічних ефектів](https://en.wikipedia.org/wiki/Side_effect_(computer_science)), і відкриваєте можливості для нових функцій у вашому додатку, таких як реалізація undo/redo, а також спрощуєте налагодження. Наприклад, ви могли б реєструвати кожну зміну стану і зберігати історію змін, щоб зрозуміти джерело помилки. +Щоб уникнути змін об'єкта `state`, також є гарною практикою вважати його [*незмінним*](https://uk.wikipedia.org/wiki/Незмінний_об'єкт), тобто таким, що не може бути змінений взагалі. Це також означає, що вам потрібно створити новий об'єкт стану, якщо ви хочете щось у ньому змінити. Таким чином, ви захищаєтеся від потенційно небажаних [побічних ефектів](https://uk.wikipedia.org/wiki/Побічний_ефект_(інформатика)) і відкриваєте можливості для нових функцій у вашому додатку, таких як реалізація скасування/повтору, а також спрощуєте налагодження. Наприклад, ви могли б реєструвати кожну зміну стану і зберігати історію змін, щоб зрозуміти джерело помилки. -У JavaScript ви можете використовувати [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) для створення незмінної версії об'єкта. Якщо ви спробуєте внести зміни до незмінного об'єкта, буде викликано виняток. +У JavaScript ви можете використовувати [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), щоб створити незмінну версію об'єкта. Якщо ви спробуєте внести зміни до незмінного об'єкта, буде викликано виняток. ✅ Чи знаєте ви різницю між *поверхневим* і *глибоким* незмінним об'єктом? Ви можете прочитати про це [тут](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze). @@ -110,9 +110,9 @@ function updateState(property, newData) { } ``` -У цій функції ми створюємо новий об'єкт стану і копіюємо дані з попереднього стану за допомогою [*оператора розгортання (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Потім ми перевизначаємо конкретну властивість об'єкта стану новими даними, використовуючи [нотацію квадратних дужок](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` для присвоєння. Нарешті, ми блокуємо об'єкт, щоб запобігти модифікаціям, використовуючи `Object.freeze()`. Зараз у стані зберігається лише властивість `account`, але з таким підходом ви можете додати стільки властивостей, скільки вам потрібно. +У цій функції ми створюємо новий об'єкт стану і копіюємо дані з попереднього стану за допомогою [*оператора розпакування (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Потім ми перевизначаємо певну властивість об'єкта стану новими даними, використовуючи [нотацію з квадратними дужками](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` для присвоєння. Нарешті, ми блокуємо об'єкт, щоб запобігти модифікаціям, використовуючи `Object.freeze()`. Зараз у нас є лише властивість `account`, збережена в стані, але з цим підходом ви можете додати стільки властивостей, скільки потрібно. -Також оновимо ініціалізацію `state`, щоб переконатися, що початковий стан також заморожений: +Ми також оновимо ініціалізацію `state`, щоб переконатися, що початковий стан також заморожений: ```js let state = Object.freeze({ @@ -126,13 +126,13 @@ let state = Object.freeze({ updateState('account', result); ``` -Зробіть те ж саме з функцією `login`, замінивши `state.account = data;` на: +Те ж саме зробіть із функцією `login`, замінивши `state.account = data;` на: ```js updateState('account', data); ``` -Тепер скористаємося можливістю вирішити проблему з даними облікового запису, які не очищаються, коли користувач натискає *Вийти*. +Тепер скористаємося можливістю виправити проблему з тим, що дані облікового запису не очищаються, коли користувач натискає *Вийти*. Створіть нову функцію `logout()`: @@ -145,47 +145,47 @@ function logout() { У `updateDashboard()` замініть перенаправлення `return navigate('/login');` на `return logout();` -Спробуйте зареєструвати новий обліковий запис, вийти і знову увійти, щоб перевірити, чи все працює правильно. +Спробуйте зареєструвати новий обліковий запис, вийти і знову увійти, щоб переконатися, що все працює правильно. -> Порада: ви можете переглянути всі зміни стану, додавши `console.log(state)` в кінці `updateState()` і відкривши консоль у засобах розробки вашого браузера. +> Порада: ви можете переглянути всі зміни стану, додавши `console.log(state)` в кінці `updateState()` і відкривши консоль у засобах розробника вашого браузера. ## Збереження стану -Більшість веб-додатків потребують збереження даних для коректної роботи. Усі критичні дані зазвичай зберігаються в базі даних і доступні через серверний API, як у нашому випадку з даними облікового запису користувача. Але іноді також цікаво зберігати деякі дані в клієнтському додатку, який працює у вашому браузері, для покращення досвіду користувача або підвищення продуктивності завантаження. +Більшість веб-додатків потребують збереження даних для коректної роботи. Усі критичні дані зазвичай зберігаються в базі даних і доступні через серверний API, як у нашому випадку з даними облікового запису користувача. Але іноді також цікаво зберігати деякі дані на клієнтському додатку, який працює у вашому браузері, для кращого користувацького досвіду або для покращення продуктивності завантаження. -Коли ви хочете зберігати дані у вашому браузері, є кілька важливих питань, які варто задати собі: +Коли ви хочете зберігати дані у вашому браузері, є кілька важливих питань, які варто задати: - *Чи є дані конфіденційними?* Ви повинні уникати зберігання будь-яких конфіденційних даних на клієнті, таких як паролі користувачів. -- *Як довго вам потрібно зберігати ці дані?* Ви плануєте отримувати доступ до цих даних лише протягом поточного сеансу чи хочете, щоб вони зберігалися назавжди? +- *Як довго вам потрібно зберігати ці дані?* Ви плануєте отримувати доступ до цих даних лише під час поточного сеансу чи хочете, щоб вони зберігалися назавжди? -Існує кілька способів зберігання інформації всередині веб-додатку, залежно від того, що ви хочете досягти. Наприклад, ви можете використовувати URL-адреси для зберігання пошукового запиту і зробити його доступним для спільного використання між користувачами. Ви також можете використовувати [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), якщо дані потрібно передавати на сервер, наприклад, інформацію для [автентифікації](https://en.wikipedia.org/wiki/Authentication). +Існує кілька способів зберігання інформації у веб-додатку, залежно від того, чого ви хочете досягти. Наприклад, ви можете використовувати URL-адреси для зберігання пошукового запиту і зробити його доступним для інших користувачів. Ви також можете використовувати [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies), якщо дані потрібно передавати на сервер, наприклад, інформацію для [автентифікації](https://uk.wikipedia.org/wiki/Автентифікація). -Ще один варіант — використовувати один із багатьох API браузера для зберігання даних. Два з них особливо цікаві: +Інший варіант — використовувати один із багатьох API браузера для зберігання даних. Два з них є особливо цікавими: -- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Сховище ключ/значення](https://en.wikipedia.org/wiki/Key%E2%80%93value_database), яке дозволяє зберігати дані, специфічні для поточного веб-сайту, між різними сеансами. Дані, збережені в ньому, ніколи не закінчуються. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): працює так само, як `localStorage`, за винятком того, що дані, збережені в ньому, очищуються після завершення сеансу (коли браузер закривається). +- [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): [Сховище ключ/значення](https://uk.wikipedia.org/wiki/База_даних_ключ-значення), яке дозволяє зберігати дані, специфічні для поточного веб-сайту, між різними сеансами. Збережені дані ніколи не закінчуються. +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): працює так само, як `localStorage`, за винятком того, що дані, збережені в ньому, очищаються після завершення сеансу (коли браузер закривається). Зверніть увагу, що обидва ці API дозволяють зберігати лише [рядки](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Якщо ви хочете зберігати складні об'єкти, вам потрібно буде серіалізувати їх у формат [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) за допомогою [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Якщо ви хочете створити веб-додаток, який не працює з сервером, також можливо створити базу даних на клієнті, використовуючи API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Цей варіант зарезервований для складних випадків використання або якщо вам потрібно зберігати значну кількість даних, оскільки він складніший у використанні. +✅ Якщо ви хочете створити веб-додаток, який не працює з сервером, також можливо створити базу даних на клієнті, використовуючи [`IndexedDB` API](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Цей варіант зарезервований для складних випадків використання або якщо вам потрібно зберігати значну кількість даних, оскільки він складніший у використанні. ### Завдання -Ми хочемо, щоб наші користувачі залишалися в системі, поки вони явно не натиснуть кнопку *Вийти*, тому ми будемо використовувати `localStorage` для зберігання даних облікового запису. Спочатку визначимо ключ, який будемо використовувати для зберігання наших даних. +Ми хочемо, щоб наші користувачі залишалися в системі, поки вони явно не натиснуть кнопку *Вийти*, тому ми будемо використовувати `localStorage` для зберігання даних облікового запису. Спочатку визначимо ключ, який ми будемо використовувати для зберігання наших даних. ```js const storageKey = 'savedAccount'; ``` -Потім додайте цей рядок у кінці функції `updateState()`: +Потім додайте цей рядок у кінець функції `updateState()`: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); ``` -Завдяки цьому дані облікового запису користувача будуть збережені і завжди актуальні, оскільки ми централізували всі оновлення стану раніше. Тут ми починаємо отримувати вигоду від усіх наших попередніх рефакторингів 🙂. +Таким чином, дані облікового запису користувача будуть збережені і завжди актуальні, оскільки ми централізували всі оновлення стану. Це той момент, коли ми починаємо отримувати вигоду від усіх наших попередніх рефакторингів 🙂. -Оскільки дані зберігаються, ми також повинні подбати про їх відновлення, коли додаток завантажується. Оскільки ми почнемо мати більше коду для ініціалізації, можливо, буде хорошою ідеєю створити нову функцію `init`, яка також включає наш попередній код у кінці `app.js`: +Оскільки дані зберігаються, ми також повинні подбати про їх відновлення під час завантаження додатка. Оскільки у нас починає з'являтися більше коду ініціалізації, можливо, варто створити нову функцію `init`, яка також включає наш попередній код у кінці `app.js`: ```js function init() { @@ -202,17 +202,17 @@ function init() { init(); ``` -Тут ми отримуємо збережені дані, і якщо вони є, ми оновлюємо стан відповідно. Важливо зробити це *перед* оновленням маршруту, оскільки може бути код, який залежить від стану під час оновлення сторінки. +Тут ми отримуємо збережені дані, і якщо вони є, оновлюємо стан відповідно. Важливо зробити це *до* оновлення маршруту, оскільки під час оновлення сторінки може бути код, який залежить від стану. -Ми також можемо зробити сторінку *Dashboard* сторінкою за замовчуванням нашого додатку, оскільки тепер ми зберігаємо дані облікового запису. Якщо дані не знайдені, інформаційна панель все одно перенаправляє на сторінку *Login*. У `updateRoute()` замініть резервний варіант `return navigate('/login');` на `return navigate('/dashboard');`. +Ми також можемо зробити сторінку *Dashboard* сторінкою за замовчуванням нашого додатка, оскільки тепер ми зберігаємо дані облікового запису. Якщо дані не знайдені, інформаційна панель все одно перенаправляє на сторінку *Login*. У `updateRoute()` замініть резервний варіант `return navigate('/login');` на `return navigate('/dashboard');`. -Тепер увійдіть у додаток і спробуйте оновити сторінку. Ви повинні залишитися на інформаційній панелі. Завдяки цьому оновленню ми вирішили всі наші початкові проблеми... +Тепер увійдіть у додаток і спробуйте оновити сторінку. Ви повинні залишитися на інформаційній панелі. З цим оновленням ми вирішили всі наші початкові проблеми... ## Оновлення даних -...Але ми також могли створити нову проблему. Ой! +...Але ми могли також створити нову проблему. Ой! -Перейдіть на інформаційну панель, використовуючи обліковий запис `test`, а потім виконайте цю команду в терміналі, щоб створити нову транзакцію: +Перейдіть на інформаційну панель, використовуючи обліковий запис `test`, потім виконайте цю команду в терміналі, щоб створити нову транзакцію: ```sh curl --request POST \ @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Тепер спробуйте оновити сторінку інформаційної панелі у браузері. Що відбувається? Ви бачите нову транзакцію? +Тепер спробуйте оновити сторінку інформаційної панелі у браузері. Що відбувається? Чи бачите ви нову транзакцію? -Стан зберігається безстроково завдяки `localStorage`, але це також означає, що він ніколи не оновлюється, поки ви не вийдете з додатку і знову не увійдете! +Стан зберігається на невизначений час завдяки `localStorage`, але це також означає, що він ніколи не оновлюється, поки ви не вийдете з додатка і не ввійдете знову! -Одна з можливих стратегій вирішення цієї проблеми — перезавантажувати дані облікового запису кожного разу, коли завантажується інформаційна панель, щоб уникнути застарілих даних. +Однією з можливих стратегій вирішення цієї проблеми є перезавантаження даних облікового запису щоразу, коли завантажується інформаційна панель, щоб уникнути застарілих даних. ### Завдання @@ -249,7 +249,7 @@ async function updateAccountData() { Цей метод перевіряє, чи ви зараз увійшли в систему, а потім перезавантажує дані облікового запису з сервера. -Створіть ще одну функцію під назвою `refresh`: +Створіть іншу функцію під назвою `refresh`: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -Ця функція оновлює дані облікового запису, а потім займається оновленням HTML сторінки інформаційної панелі. Це те, що нам потрібно викликати, коли завантажується маршрут інформаційної панелі. Оновіть визначення маршруту: +Ця функція оновлює дані облікового запису, а потім оновлює HTML сторінки інформаційної панелі. Це те, що нам потрібно викликати, коли завантажується маршрут інформаційної панелі. Оновіть визначення маршруту: ```js const routes = { @@ -273,10 +273,12 @@ const routes = { ## 🚀 Виклик -Тепер, коли ми перезавантажуємо дані облікового запису кожного разу, коли завантажується інформаційна панель, як ви думаєте, чи потрібно нам все ще зберігати *всі дані облікового запису*? +Тепер, коли ми перезавантажуємо дані облікового запису щоразу, коли завантажується інформаційна панель, як ви думаєте, чи потрібно нам все ще з +[Тест після лекції](https://ff-quizzes.netlify.app/web/quiz/48) -Спробуйте разом зм -[Реалізуйте діалогове вікно "Додати транзакцію"](assignment.md) +## Завдання + +[Реалізувати діалогове вікно "Додати транзакцію"](assignment.md) Ось приклад результату після виконання завдання: @@ -285,4 +287,4 @@ const routes = { --- **Відмова від відповідальності**: -Цей документ було перекладено за допомогою сервісу автоматичного перекладу [Co-op Translator](https://github.com/Azure/co-op-translator). Хоча ми прагнемо до точності, зверніть увагу, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ мовою оригіналу слід вважати авторитетним джерелом. Для критично важливої інформації рекомендується професійний переклад людиною. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникли внаслідок використання цього перекладу. \ No newline at end of file +Цей документ було перекладено за допомогою сервісу автоматичного перекладу [Co-op Translator](https://github.com/Azure/co-op-translator). Хоча ми прагнемо до точності, будь ласка, зверніть увагу, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ на його рідній мові слід вважати авторитетним джерелом. Для критичної інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникають внаслідок використання цього перекладу. \ No newline at end of file diff --git a/translations/ur/7-bank-project/4-state-management/README.md b/translations/ur/7-bank-project/4-state-management/README.md index 64d4039ca..374dbe9ce 100644 --- a/translations/ur/7-bank-project/4-state-management/README.md +++ b/translations/ur/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@ -# Xây dựng Ứng dụng Ngân hàng Phần 4: Khái niệm Quản lý Trạng thái +# Xây dựng ứng dụng ngân hàng Phần 4: Khái niệm về Quản lý trạng thái ## Câu hỏi trước bài giảng @@ -15,13 +15,13 @@ CO_OP_TRANSLATOR_METADATA: ### Giới thiệu -Khi một ứng dụng web phát triển, việc theo dõi tất cả các luồng dữ liệu trở nên thách thức. Mã nào lấy dữ liệu, trang nào sử dụng nó, dữ liệu cần được cập nhật ở đâu và khi nào... rất dễ dẫn đến mã lộn xộn và khó bảo trì. Điều này đặc biệt đúng khi bạn cần chia sẻ dữ liệu giữa các trang khác nhau trong ứng dụng, chẳng hạn như dữ liệu người dùng. Khái niệm *quản lý trạng thái* luôn tồn tại trong mọi loại chương trình, nhưng khi các ứng dụng web ngày càng phức tạp, đây trở thành một điểm quan trọng cần suy nghĩ trong quá trình phát triển. +Khi một ứng dụng web phát triển, việc theo dõi tất cả các luồng dữ liệu trở nên thách thức. Mã nào nhận dữ liệu, trang nào sử dụng nó, nơi nào và khi nào cần cập nhật... rất dễ dẫn đến mã lộn xộn và khó bảo trì. Điều này đặc biệt đúng khi bạn cần chia sẻ dữ liệu giữa các trang khác nhau của ứng dụng, ví dụ như dữ liệu người dùng. Khái niệm *quản lý trạng thái* luôn tồn tại trong mọi loại chương trình, nhưng khi các ứng dụng web ngày càng phức tạp, đây trở thành một điểm quan trọng cần suy nghĩ trong quá trình phát triển. Trong phần cuối này, chúng ta sẽ xem xét lại ứng dụng đã xây dựng để suy nghĩ lại cách quản lý trạng thái, cho phép hỗ trợ làm mới trình duyệt tại bất kỳ thời điểm nào và duy trì dữ liệu qua các phiên người dùng. ### Điều kiện tiên quyết -Bạn cần hoàn thành phần [lấy dữ liệu](../3-data/README.md) của ứng dụng web trong bài học này. Bạn cũng cần cài đặt [Node.js](https://nodejs.org) và [chạy API máy chủ](../api/README.md) cục bộ để quản lý dữ liệu tài khoản. +Bạn cần hoàn thành phần [lấy dữ liệu](../3-data/README.md) của ứng dụng web cho bài học này. Bạn cũng cần cài đặt [Node.js](https://nodejs.org) và [chạy API máy chủ](../api/README.md) cục bộ để quản lý dữ liệu tài khoản. Bạn có thể kiểm tra xem máy chủ có chạy đúng không bằng cách thực hiện lệnh này trong terminal: @@ -39,25 +39,25 @@ Trong [bài học trước](../3-data/README.md), chúng ta đã giới thiệu Có 3 vấn đề với mã hiện tại: - Trạng thái không được duy trì, vì làm mới trình duyệt sẽ đưa bạn trở lại trang đăng nhập. -- Có nhiều hàm sửa đổi trạng thái. Khi ứng dụng phát triển, điều này có thể khiến việc theo dõi các thay đổi trở nên khó khăn và dễ quên cập nhật một số phần. +- Có nhiều hàm sửa đổi trạng thái. Khi ứng dụng phát triển, điều này có thể khiến việc theo dõi các thay đổi trở nên khó khăn và dễ quên cập nhật một hàm. - Trạng thái không được dọn dẹp, vì vậy khi bạn nhấp vào *Đăng xuất*, dữ liệu tài khoản vẫn còn đó mặc dù bạn đang ở trang đăng nhập. -Chúng ta có thể cập nhật mã để giải quyết từng vấn đề này, nhưng điều đó sẽ tạo ra sự trùng lặp mã và làm cho ứng dụng phức tạp hơn và khó bảo trì hơn. Hoặc chúng ta có thể dừng lại vài phút và suy nghĩ lại chiến lược của mình. +Chúng ta có thể cập nhật mã để giải quyết từng vấn đề một, nhưng điều này sẽ tạo ra sự trùng lặp mã và làm cho ứng dụng phức tạp hơn và khó bảo trì hơn. Hoặc chúng ta có thể dừng lại vài phút và suy nghĩ lại chiến lược của mình. -> Vấn đề thực sự mà chúng ta đang cố gắng giải quyết ở đây là gì? +> Những vấn đề thực sự chúng ta đang cố gắng giải quyết ở đây là gì? -[Quản lý trạng thái](https://en.wikipedia.org/wiki/State_management) là tất cả về việc tìm ra một cách tiếp cận tốt để giải quyết hai vấn đề cụ thể này: +[Quản lý trạng thái](https://en.wikipedia.org/wiki/State_management) là tất cả về việc tìm một cách tiếp cận tốt để giải quyết hai vấn đề cụ thể này: - Làm thế nào để giữ cho các luồng dữ liệu trong ứng dụng dễ hiểu? - Làm thế nào để giữ cho dữ liệu trạng thái luôn đồng bộ với giao diện người dùng (và ngược lại)? -Khi bạn đã giải quyết được những vấn đề này, bất kỳ vấn đề nào khác mà bạn có thể gặp phải có thể đã được khắc phục hoặc trở nên dễ dàng hơn để giải quyết. Có nhiều cách tiếp cận khác nhau để giải quyết những vấn đề này, nhưng chúng ta sẽ chọn một giải pháp phổ biến bao gồm **tập trung hóa dữ liệu và cách thay đổi nó**. Các luồng dữ liệu sẽ diễn ra như sau: +Khi bạn đã giải quyết được những vấn đề này, bất kỳ vấn đề nào khác bạn có thể gặp phải có thể đã được giải quyết hoặc trở nên dễ dàng hơn để giải quyết. Có nhiều cách tiếp cận khả thi để giải quyết những vấn đề này, nhưng chúng ta sẽ chọn một giải pháp phổ biến bao gồm **tập trung hóa dữ liệu và cách thay đổi nó**. Các luồng dữ liệu sẽ diễn ra như sau: ![Sơ đồ hiển thị luồng dữ liệu giữa HTML, hành động người dùng và trạng thái](../../../../translated_images/data-flow.fa2354e0908fecc89b488010dedf4871418a992edffa17e73441d257add18da4.vi.png) -> Chúng ta sẽ không đề cập đến phần mà dữ liệu tự động kích hoạt cập nhật giao diện, vì nó liên quan đến các khái niệm nâng cao hơn về [Lập trình Phản ứng](https://en.wikipedia.org/wiki/Reactive_programming). Đây là một chủ đề tiếp theo tốt nếu bạn muốn tìm hiểu sâu hơn. +> Chúng ta sẽ không đề cập đến phần dữ liệu tự động kích hoạt cập nhật giao diện, vì nó liên quan đến các khái niệm nâng cao hơn về [Lập trình phản ứng](https://en.wikipedia.org/wiki/Reactive_programming). Đây là một chủ đề tiếp theo tốt nếu bạn muốn tìm hiểu sâu hơn. -✅ Có rất nhiều thư viện ngoài kia với các cách tiếp cận khác nhau để quản lý trạng thái, [Redux](https://redux.js.org) là một lựa chọn phổ biến. Hãy xem các khái niệm và mẫu được sử dụng vì đây thường là một cách tốt để học về các vấn đề tiềm năng mà bạn có thể gặp phải trong các ứng dụng web lớn và cách giải quyết chúng. +✅ Có rất nhiều thư viện ngoài kia với các cách tiếp cận khác nhau về quản lý trạng thái, [Redux](https://redux.js.org) là một lựa chọn phổ biến. Hãy xem các khái niệm và mẫu được sử dụng vì nó thường là một cách tốt để học về các vấn đề tiềm năng bạn có thể gặp phải trong các ứng dụng web lớn và cách giải quyết chúng. ### Nhiệm vụ @@ -75,9 +75,9 @@ let state = { }; ``` -Ý tưởng là *tập trung hóa* tất cả dữ liệu ứng dụng của chúng ta trong một đối tượng trạng thái duy nhất. Hiện tại chúng ta chỉ có `account` trong trạng thái nên nó không thay đổi nhiều, nhưng nó tạo ra một con đường cho các cải tiến sau này. +Ý tưởng là *tập trung hóa* tất cả dữ liệu ứng dụng của chúng ta trong một đối tượng trạng thái duy nhất. Hiện tại chúng ta chỉ có `account` trong trạng thái nên không thay đổi nhiều, nhưng nó tạo ra một con đường cho các cải tiến. -Chúng ta cũng cần cập nhật các hàm sử dụng nó. Trong các hàm `register()` và `login()`, thay thế `account = ...` bằng `state.account = ...`; +Chúng ta cũng phải cập nhật các hàm sử dụng nó. Trong các hàm `register()` và `login()`, thay thế `account = ...` bằng `state.account = ...`; Ở đầu hàm `updateDashboard()`, thêm dòng này: @@ -91,7 +91,7 @@ Việc tái cấu trúc này tự nó không mang lại nhiều cải tiến, nh Bây giờ chúng ta đã thiết lập đối tượng `state` để lưu trữ dữ liệu, bước tiếp theo là tập trung hóa các cập nhật. Mục tiêu là làm cho việc theo dõi bất kỳ thay đổi nào và khi nào chúng xảy ra trở nên dễ dàng hơn. -Để tránh việc thay đổi đối tượng `state`, cũng là một thực hành tốt để coi nó là [*bất biến*](https://en.wikipedia.org/wiki/Immutable_object), nghĩa là nó không thể bị sửa đổi. Điều này cũng có nghĩa là bạn phải tạo một đối tượng trạng thái mới nếu muốn thay đổi bất kỳ điều gì trong đó. Bằng cách làm như vậy, bạn xây dựng một lớp bảo vệ chống lại các [tác dụng phụ](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) không mong muốn, và mở ra khả năng cho các tính năng mới trong ứng dụng của bạn như triển khai hoàn tác/làm lại, đồng thời làm cho việc gỡ lỗi trở nên dễ dàng hơn. Ví dụ, bạn có thể ghi lại mọi thay đổi được thực hiện đối với trạng thái và giữ lịch sử các thay đổi để hiểu nguồn gốc của lỗi. +Để tránh việc thay đổi đối tượng `state`, cũng là một thực hành tốt để coi nó là [*bất biến*](https://en.wikipedia.org/wiki/Immutable_object), nghĩa là nó không thể bị sửa đổi. Điều này cũng có nghĩa là bạn phải tạo một đối tượng trạng thái mới nếu muốn thay đổi bất kỳ điều gì trong đó. Bằng cách làm điều này, bạn xây dựng một sự bảo vệ chống lại các [tác động phụ](https://en.wikipedia.org/wiki/Side_effect_(computer_science)) không mong muốn, và mở ra các khả năng cho các tính năng mới trong ứng dụng của bạn như triển khai hoàn tác/làm lại, đồng thời làm cho việc gỡ lỗi trở nên dễ dàng hơn. Ví dụ, bạn có thể ghi lại mọi thay đổi được thực hiện đối với trạng thái và giữ lịch sử các thay đổi để hiểu nguồn gốc của lỗi. Trong JavaScript, bạn có thể sử dụng [`Object.freeze()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) để tạo một phiên bản bất biến của một đối tượng. Nếu bạn cố gắng thực hiện thay đổi đối với một đối tượng bất biến, một ngoại lệ sẽ được đưa ra. @@ -110,7 +110,7 @@ function updateState(property, newData) { } ``` -Trong hàm này, chúng ta tạo một đối tượng trạng thái mới và sao chép dữ liệu từ trạng thái trước đó bằng cách sử dụng [*toán tử spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Sau đó, chúng ta ghi đè một thuộc tính cụ thể của đối tượng trạng thái với dữ liệu mới bằng cách sử dụng [cú pháp ngoặc vuông](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` để gán giá trị. Cuối cùng, chúng ta khóa đối tượng để ngăn chặn các sửa đổi bằng `Object.freeze()`. Hiện tại chúng ta chỉ có thuộc tính `account` được lưu trữ trong trạng thái, nhưng với cách tiếp cận này, bạn có thể thêm bao nhiêu thuộc tính tùy ý vào trạng thái. +Trong hàm này, chúng ta tạo một đối tượng trạng thái mới và sao chép dữ liệu từ trạng thái trước đó bằng [*toán tử spread (`...`)*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals). Sau đó, chúng ta ghi đè một thuộc tính cụ thể của đối tượng trạng thái với dữ liệu mới bằng [cú pháp ngoặc vuông](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` để gán. Cuối cùng, chúng ta khóa đối tượng để ngăn chặn các sửa đổi bằng `Object.freeze()`. Hiện tại chúng ta chỉ có thuộc tính `account` được lưu trữ trong trạng thái, nhưng với cách tiếp cận này bạn có thể thêm bao nhiêu thuộc tính tùy thích vào trạng thái. Chúng ta cũng sẽ cập nhật khởi tạo `state` để đảm bảo trạng thái ban đầu cũng được đóng băng: @@ -120,7 +120,7 @@ let state = Object.freeze({ }); ``` -Sau đó, cập nhật hàm `register` bằng cách thay thế `state.account = result;` bằng: +Sau đó, cập nhật hàm `register` bằng cách thay thế `state.account = result;` với: ```js updateState('account', result); @@ -132,7 +132,7 @@ Làm tương tự với hàm `login`, thay thế `state.account = data;` bằng: updateState('account', data); ``` -Chúng ta sẽ nhân cơ hội này để sửa lỗi dữ liệu tài khoản không được xóa khi người dùng nhấp vào *Đăng xuất*. +Chúng ta sẽ tận dụng cơ hội này để sửa lỗi dữ liệu tài khoản không được xóa khi người dùng nhấp vào *Đăng xuất*. Tạo một hàm mới `logout()`: @@ -143,41 +143,41 @@ function logout() { } ``` -Trong `updateDashboard()`, thay thế chuyển hướng `return navigate('/login');` bằng `return logout();` +Trong `updateDashboard()`, thay thế chuyển hướng `return navigate('/login');` bằng `return logout()`; -Hãy thử đăng ký một tài khoản mới, đăng xuất và đăng nhập lại để kiểm tra xem mọi thứ vẫn hoạt động chính xác. +Hãy thử đăng ký một tài khoản mới, đăng xuất và đăng nhập lại để kiểm tra rằng mọi thứ vẫn hoạt động đúng. > Mẹo: bạn có thể xem tất cả các thay đổi trạng thái bằng cách thêm `console.log(state)` ở cuối `updateState()` và mở bảng điều khiển trong công cụ phát triển của trình duyệt. ## Duy trì trạng thái -Hầu hết các ứng dụng web cần duy trì dữ liệu để hoạt động chính xác. Tất cả dữ liệu quan trọng thường được lưu trữ trong cơ sở dữ liệu và truy cập thông qua API máy chủ, như dữ liệu tài khoản người dùng trong trường hợp của chúng ta. Nhưng đôi khi, cũng rất hữu ích để duy trì một số dữ liệu trên ứng dụng khách đang chạy trong trình duyệt của bạn, để cải thiện trải nghiệm người dùng hoặc tăng hiệu suất tải. +Hầu hết các ứng dụng web cần duy trì dữ liệu để hoạt động đúng. Tất cả dữ liệu quan trọng thường được lưu trữ trên cơ sở dữ liệu và truy cập thông qua API máy chủ, như dữ liệu tài khoản người dùng trong trường hợp của chúng ta. Nhưng đôi khi, cũng rất thú vị để duy trì một số dữ liệu trên ứng dụng khách đang chạy trong trình duyệt, để có trải nghiệm người dùng tốt hơn hoặc cải thiện hiệu suất tải. Khi bạn muốn duy trì dữ liệu trong trình duyệt, có một số câu hỏi quan trọng bạn nên tự hỏi: - *Dữ liệu có nhạy cảm không?* Bạn nên tránh lưu trữ bất kỳ dữ liệu nhạy cảm nào trên ứng dụng khách, chẳng hạn như mật khẩu người dùng. -- *Bạn cần giữ dữ liệu này trong bao lâu?* Bạn có định truy cập dữ liệu này chỉ trong phiên hiện tại hay muốn lưu trữ nó mãi mãi? +- *Bạn cần giữ dữ liệu này trong bao lâu?* Bạn có dự định truy cập dữ liệu này chỉ trong phiên hiện tại hay muốn nó được lưu trữ mãi mãi? Có nhiều cách để lưu trữ thông tin trong một ứng dụng web, tùy thuộc vào những gì bạn muốn đạt được. Ví dụ, bạn có thể sử dụng URL để lưu trữ một truy vấn tìm kiếm và làm cho nó có thể chia sẻ giữa các người dùng. Bạn cũng có thể sử dụng [HTTP cookies](https://developer.mozilla.org/docs/Web/HTTP/Cookies) nếu dữ liệu cần được chia sẻ với máy chủ, như thông tin [xác thực](https://en.wikipedia.org/wiki/Authentication). -Một tùy chọn khác là sử dụng một trong nhiều API trình duyệt để lưu trữ dữ liệu. Hai API đặc biệt thú vị: +Một tùy chọn khác là sử dụng một trong nhiều API trình duyệt để lưu trữ dữ liệu. Hai trong số đó đặc biệt thú vị: - [`localStorage`](https://developer.mozilla.org/docs/Web/API/Window/localStorage): một [Kho lưu trữ Key/Value](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) cho phép duy trì dữ liệu cụ thể cho trang web hiện tại qua các phiên khác nhau. Dữ liệu được lưu trong đó không bao giờ hết hạn. -- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): hoạt động giống như `localStorage` ngoại trừ việc dữ liệu được lưu trong đó sẽ bị xóa khi phiên kết thúc (khi trình duyệt bị đóng). +- [`sessionStorage`](https://developer.mozilla.org/docs/Web/API/Window/sessionStorage): cái này hoạt động giống như `localStorage` ngoại trừ việc dữ liệu được lưu trữ trong đó sẽ bị xóa khi phiên kết thúc (khi trình duyệt bị đóng). -Lưu ý rằng cả hai API này chỉ cho phép lưu trữ [chuỗi](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Nếu bạn muốn lưu trữ các đối tượng phức tạp, bạn sẽ cần tuần tự hóa chúng sang định dạng [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) bằng [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). +Lưu ý rằng cả hai API này chỉ cho phép lưu trữ [chuỗi](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String). Nếu bạn muốn lưu trữ các đối tượng phức tạp, bạn sẽ cần tuần tự hóa nó sang định dạng [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) bằng [`JSON.stringify()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify). -✅ Nếu bạn muốn tạo một ứng dụng web không làm việc với máy chủ, cũng có thể tạo một cơ sở dữ liệu trên ứng dụng khách bằng API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). API này dành cho các trường hợp sử dụng nâng cao hoặc nếu bạn cần lưu trữ một lượng lớn dữ liệu, vì nó phức tạp hơn để sử dụng. +✅ Nếu bạn muốn tạo một ứng dụng web không hoạt động với máy chủ, cũng có thể tạo một cơ sở dữ liệu trên ứng dụng khách bằng API [`IndexedDB`](https://developer.mozilla.org/docs/Web/API/IndexedDB_API). Cái này dành cho các trường hợp sử dụng nâng cao hoặc nếu bạn cần lưu trữ lượng dữ liệu đáng kể, vì nó phức tạp hơn để sử dụng. ### Nhiệm vụ -Chúng ta muốn người dùng của mình vẫn đăng nhập cho đến khi họ nhấp rõ ràng vào nút *Đăng xuất*, vì vậy chúng ta sẽ sử dụng `localStorage` để lưu trữ dữ liệu tài khoản. Đầu tiên, hãy định nghĩa một khóa mà chúng ta sẽ sử dụng để lưu trữ dữ liệu của mình. +Chúng ta muốn người dùng vẫn đăng nhập cho đến khi họ nhấp vào nút *Đăng xuất*, vì vậy chúng ta sẽ sử dụng `localStorage` để lưu trữ dữ liệu tài khoản. Đầu tiên, hãy định nghĩa một khóa mà chúng ta sẽ sử dụng để lưu trữ dữ liệu của mình. ```js const storageKey = 'savedAccount'; ``` -Sau đó thêm dòng này vào cuối hàm `updateState()`: +Sau đó, thêm dòng này vào cuối hàm `updateState()`: ```js localStorage.setItem(storageKey, JSON.stringify(state.account)); @@ -185,7 +185,7 @@ localStorage.setItem(storageKey, JSON.stringify(state.account)); Với điều này, dữ liệu tài khoản người dùng sẽ được duy trì và luôn cập nhật vì chúng ta đã tập trung hóa tất cả các cập nhật trạng thái trước đó. Đây là lúc chúng ta bắt đầu hưởng lợi từ tất cả các lần tái cấu trúc trước đó 🙂. -Vì dữ liệu được lưu, chúng ta cũng cần khôi phục nó khi ứng dụng được tải. Vì chúng ta sẽ bắt đầu có nhiều mã khởi tạo hơn, có thể là một ý tưởng hay để tạo một hàm `init` mới, bao gồm cả mã trước đó ở cuối `app.js`: +Vì dữ liệu đã được lưu, chúng ta cũng phải xử lý việc khôi phục nó khi ứng dụng được tải. Vì chúng ta sẽ bắt đầu có nhiều mã khởi tạo hơn, có thể là một ý tưởng tốt để tạo một hàm mới `init`, bao gồm cả mã trước đó ở cuối `app.js`: ```js function init() { @@ -202,11 +202,11 @@ function init() { init(); ``` -Ở đây chúng ta lấy dữ liệu đã lưu, và nếu có, chúng ta cập nhật trạng thái tương ứng. Điều quan trọng là làm điều này *trước* khi cập nhật tuyến đường, vì có thể có mã phụ thuộc vào trạng thái trong quá trình cập nhật trang. +Ở đây chúng ta lấy dữ liệu đã lưu, và nếu có, chúng ta cập nhật trạng thái tương ứng. Điều quan trọng là làm điều này *trước* khi cập nhật tuyến đường, vì có thể có mã dựa vào trạng thái trong quá trình cập nhật trang. -Chúng ta cũng có thể làm cho trang *Dashboard* trở thành trang mặc định của ứng dụng, vì bây giờ chúng ta đang duy trì dữ liệu tài khoản. Nếu không tìm thấy dữ liệu, bảng điều khiển sẽ tự động chuyển hướng đến trang *Login*. Trong `updateRoute()`, thay thế dự phòng `return navigate('/login');` bằng `return navigate('/dashboard');`. +Chúng ta cũng có thể làm cho trang *Dashboard* trở thành trang mặc định của ứng dụng, vì bây giờ chúng ta đang duy trì dữ liệu tài khoản. Nếu không tìm thấy dữ liệu, bảng điều khiển sẽ xử lý việc chuyển hướng đến trang *Login* dù sao đi nữa. Trong `updateRoute()`, thay thế dự phòng `return navigate('/login');` bằng `return navigate('/dashboard');`. -Bây giờ hãy đăng nhập vào ứng dụng và thử làm mới trang. Bạn sẽ vẫn ở trên bảng điều khiển. Với bản cập nhật này, chúng ta đã giải quyết tất cả các vấn đề ban đầu... +Bây giờ đăng nhập vào ứng dụng và thử làm mới trang. Bạn sẽ vẫn ở trên bảng điều khiển. Với bản cập nhật đó, chúng ta đã giải quyết tất cả các vấn đề ban đầu... ## Làm mới dữ liệu @@ -221,11 +221,11 @@ curl --request POST \ http://localhost:5000/api/accounts/test/transactions ``` -Thử làm mới trang bảng điều khiển trong trình duyệt bây giờ. Điều gì xảy ra? Bạn có thấy giao dịch mới không? +Thử làm mới trang bảng điều khiển của bạn trong trình duyệt bây giờ. Điều gì xảy ra? Bạn có thấy giao dịch mới không? Trạng thái được duy trì vô thời hạn nhờ `localStorage`, nhưng điều đó cũng có nghĩa là nó không bao giờ được cập nhật cho đến khi bạn đăng xuất khỏi ứng dụng và đăng nhập lại! -Một chiến lược khả thi để khắc phục điều đó là tải lại dữ liệu tài khoản mỗi khi bảng điều khiển được tải, để tránh dữ liệu bị lỗi thời. +Một chiến lược khả thi để khắc phục điều đó là tải lại dữ liệu tài khoản mỗi khi bảng điều khiển được tải, để tránh dữ liệu bị trì trệ. ### Nhiệm vụ @@ -247,9 +247,9 @@ async function updateAccountData() { } ``` -Phương thức này kiểm tra xem chúng ta hiện đang đăng nhập hay không, sau đó tải lại dữ liệu tài khoản từ máy chủ. +Phương pháp này kiểm tra rằng chúng ta hiện đang đăng nhập sau đó tải lại dữ liệu tài khoản từ máy chủ. -Tạo một hàm khác có tên `refresh`: +Tạo một hàm khác tên là `refresh`: ```js async function refresh() { @@ -258,7 +258,7 @@ async function refresh() { } ``` -Hàm này cập nhật dữ liệu tài khoản, sau đó xử lý việc cập nhật HTML của trang bảng điều khiển. Đây là hàm chúng ta cần gọi khi tuyến đường bảng điều khiển được tải. Cập nhật định nghĩa tuyến đường với: +Hàm này cập nhật dữ liệu tài khoản, sau đó xử lý việc cập nhật HTML của trang bảng điều khiển. Đây là điều chúng ta cần gọi khi tuyến đường bảng điều khiển được tải. Cập nhật định nghĩa tuyến đường với: ```js const routes = { @@ -267,7 +267,7 @@ const routes = { }; ``` -Thử làm mới bảng điều khiển bây giờ, nó sẽ hiển thị dữ liệu tài khoản đã cập nhật. +Thử làm mới bảng điều khiển bây giờ, nó sẽ hiển thị dữ liệu tài khoản đã được cập nhật. --- @@ -275,20 +275,20 @@ Thử làm mới bảng điều khiển bây giờ, nó sẽ hiển thị dữ l Bây giờ chúng ta tải lại dữ liệu tài khoản mỗi khi bảng điều khiển được tải, bạn có nghĩ rằng chúng ta vẫn cần duy trì *toàn bộ dữ liệu tài khoản* không? -Hãy thử làm việc cùng nhau để thay đổi những gì được lưu và tải từ `localStorage` để chỉ bao gồm những gì thực sự cần thiết cho ứng dụng hoạt động. +Hãy thử làm việc cùng nhau để thay đổi những gì được lưu và tải từ `localStorage` chỉ bao gồm những gì thực sự cần thiết để ứng dụng hoạt động. ## Câu hỏi sau bài giảng - -[Câu hỏi sau bài giảng](https://ff-quizzes.netlify.app/web/quiz/48) +[Quiz sau bài giảng](https://ff-quizzes.netlify.app/web/quiz/48) ## Bài tập -[Thực hiện hộp thoại "Thêm giao dịch"](assignment.md) -Dưới đây là một ví dụ kết quả sau khi hoàn thành nhiệm vụ: +[Triển khai hộp thoại "Thêm giao dịch"](assignment.md) + +Dưới đây là một ví dụ kết quả sau khi hoàn thành bài tập: -![Ảnh chụp màn hình hiển thị hộp thoại "Thêm giao dịch" mẫu](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.vi.png) +![Ảnh chụp màn hình hiển thị ví dụ hộp thoại "Thêm giao dịch"](../../../../translated_images/dialog.93bba104afeb79f12f65ebf8f521c5d64e179c40b791c49c242cf15f7e7fab15.vi.png) --- **Tuyên bố miễn trừ trách nhiệm**: -Tài liệu này đã được dịch bằng dịch vụ dịch thuật AI [Co-op Translator](https://github.com/Azure/co-op-translator). Mặc dù chúng tôi cố gắng đảm bảo độ chính xác, xin lưu ý rằng các bản dịch tự động có thể chứa lỗi hoặc không chính xác. Tài liệu gốc bằng ngôn ngữ bản địa nên được coi là nguồn tham khảo chính thức. Đối với các thông tin quan trọng, nên sử dụng dịch vụ dịch thuật chuyên nghiệp từ con người. Chúng tôi không chịu trách nhiệm cho bất kỳ sự hiểu lầm hoặc diễn giải sai nào phát sinh từ việc sử dụng bản dịch này. \ No newline at end of file +Tài liệu này đã được dịch bằng dịch vụ dịch thuật AI [Co-op Translator](https://github.com/Azure/co-op-translator). Mặc dù chúng tôi cố gắng đảm bảo độ chính xác, xin lưu ý rằng các bản dịch tự động có thể chứa lỗi hoặc không chính xác. Tài liệu gốc bằng ngôn ngữ bản địa nên được coi là nguồn thông tin chính thức. Đối với các thông tin quan trọng, khuyến nghị sử dụng dịch vụ dịch thuật chuyên nghiệp bởi con người. Chúng tôi không chịu trách nhiệm cho bất kỳ sự hiểu lầm hoặc diễn giải sai nào phát sinh từ việc sử dụng bản dịch này. \ No newline at end of file diff --git a/translations/zh/7-bank-project/4-state-management/README.md b/translations/zh/7-bank-project/4-state-management/README.md index c4448750b..43b0867be 100644 --- a/translations/zh/7-bank-project/4-state-management/README.md +++ b/translations/zh/7-bank-project/4-state-management/README.md @@ -1,8 +1,8 @@