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

16 KiB

Banki alkalmazás építése 4. rész: Az állapotkezelés alapjai

Előadás előtti kvíz

Előadás előtti kvíz

Bevezetés

Ahogy egy webalkalmazás növekszik, egyre nehezebb nyomon követni az adatáramlásokat. 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 lesz karbantartani. Ez különösen igaz, ha az adatokat több oldal között kell megosztani az alkalmazásban, 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.

Ebben az utolsó részben áttekintjük az eddig épített alkalmazást, hogy újragondoljuk az állapotkezelést, lehetővé téve a böngésző frissítésének támogatását bármely ponton, és az adatok megőrzését a felhasználói munkamenetek között.

Előfeltétel

El kell végezned a webalkalmazás adatlekérdezés részét ehhez a leckéhez. Telepítened kell a Node.js programot, és futtatnod kell a szerver API-t helyileg, hogy kezelhesd a fiókadatokat.

Ellenőrizheted, hogy a szerver megfelelően fut-e, ha végrehajtod ezt a parancsot egy terminálban:

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

Az állapotkezelés újragondolása

Az előző leckében bevezettünk egy alapvető állapotfogalmat az alkalmazásunkban a globális account változóval, amely a jelenleg bejelentkezett felhasználó banki adatait tartalmazza. 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ó is módosítja az állapotot. Ahogy az alkalmazás növekszik, nehéz lehet nyomon követni a változásokat, és könnyen elfelejthetjük frissíteni az egyiket.
  • Az állapot nincs törölve, í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 lényege, hogy megtaláljuk a megfelelő megközelítést 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 ezekkel foglalkoztál, bármilyen más probléma, amivel szembesülsz, 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 általános megoldást választunk, amely abból áll, hogy központosítjuk az adatokat és a változtatás módjait. Az adatáramlások így néznének ki:

Séma, amely az adatáramlásokat mutatja a HTML, a felhasználói műveletek és az állapot között

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 fejlettebb fogalmaihoz kapcsolódik. Ez egy jó következő téma, ha mélyebben bele szeretnél merülni.

Számos könyvtár létezik különböző megközelítésekkel az állapotkezeléshez, például a Redux, amely egy népszerű opció. Nézd meg a használt fogalmakat és mintákat, mivel ez gyakran jó módja annak, hogy megértsd, milyen potenciális problémákkal szembesülhetsz nagy webalkalmazásokban, és hogyan lehet ezeket megoldani.

Feladat

Kezdjünk egy kis refaktorálással. Cseréld ki az account deklarációt:

let account = null;

Erre:

let state = {
  account: null
};

Az ötlet az, hogy központosítsuk az összes alkalmazásadatot egyetlen állapotobjektumban. Jelenleg csak az account van az állapotban, így ez nem sokat változtat, 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 ki az account = ... sort state.account = ...-ra.

Az updateDashboard() függvény tetején add hozzá ezt a sort:

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.

Az adatok változásainak nyomon követése

Most, hogy létrehoztuk az state objektumot az adatok 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 az esetleges változásokat és azok időpontját.

Az state objektum módosításának elkerülése érdekében jó gyakorlatnak számít, ha azt változatlannak 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 ellen, és lehetőséget nyitsz új funkciók bevezetésére az alkalmazásodban, például visszavonás/újra végrehajtás megvalósítására, miközben megkönnyíted a hibakeresést. Például naplózhatod az állapoton végrehajtott minden változást, és nyilvántarthatod a változások történetét, hogy megértsd egy hiba forrását.

JavaScriptben az Object.freeze() használatával hozhatsz létre változatlan objektumot. Ha megpróbálsz változtatásokat végrehajtani egy változatlan objektumon, kivétel keletkezik.

Tudod, mi a különbség a sekély és a mély változatlan objektum között? Erről itt olvashatsz.

Feladat

Hozzunk létre egy új updateState() függvényt:

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

Ebben a függvényben létrehozunk egy új állapotobjektumot, és az előző állapotból másoljuk az adatokat a spread (...) operátor segítségével. Ezután felülírunk egy adott tulajdonságot az állapotobjektumban az új adatokkal a zárójel notáció [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:

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

Ezután frissítsd a register függvényt az state.account = result; helyett:

updateState('account', result);

Ugyanezt tedd a login függvénnyel, cseréld ki az state.account = data; sort:

updateState('account', data);

Most kihasználhatjuk az alkalmat, hogy kijavítsuk azt a problémát, hogy a fiókadatok nem törlődnek, amikor a felhasználó a Kijelentkezés gombra kattint.

Hozz létre egy új logout() függvényt:

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

Az updateDashboard() függvényben cseréld ki az return navigate('/login'); átirányítást return logout();-ra.

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: Nyomon követheted az összes állapotváltozást, ha hozzáadod a console.log(state) sort az updateState() függvény 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 szüksége van az adatok megőrzésére a megfelelő működés érdekében. 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 az esetünkben. De néha az is érdekes lehet, ha néhány adatot a böngésződben futó kliensalkalmazásban tárolsz, a jobb felhasználói élmény vagy a betöltési teljesítmény javítása érdekében.

Amikor adatokat szeretnél tárolni a böngésződben, néhány fontos kérdést fel kell tenned magadnak:

  • Érzékeny-e az adat? Kerüld az érzékeny adatok, például a felhasználói jelszavak tárolását a kliensen.
  • Meddig van szükséged az adatok megőrzésére? Csak az aktuális munkamenethez szeretnéd elérni ezeket az adatokat, 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 megoszthatóvá teheted más felhasználók között. Használhatsz HTTP sütiket, ha az adatokat meg kell osztani a szerverrel, például az azonosítási 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 lehetőség van:

  • localStorage: egy kulcs/érték tároló, 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.
  • 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árod).

Fontos megjegyezni, hogy mindkét API csak sztringeket képes tárolni. Ha összetett objektumokat szeretnél tárolni, akkor azokat a JSON formátumba kell sorosítanod a JSON.stringify() használatával.

Ha olyan webalkalmazást szeretnél létrehozni, amely nem működik szerverrel, az IndexedDB API használatával kliensoldali adatbázist is létrehozhatsz. Ez az opció fejlettebb esetekre vagy jelentős mennyiségű adat tárolására van fenntartva, mivel bonyolultabb a használata.

Feladat

Azt szeretnénk, hogy a felhasználók bejelentkezve maradjanak, amíg kifejezetten nem kattintanak a Kijelentkezés gombra, ezért a localStorage-t fogjuk használni a fiókadatok tárolására. Először definiáljunk egy kulcsot, amelyet az adatok tárolására használunk.

const storageKey = 'savedAccount';

Ezután add hozzá ezt a sort az updateState() függvény végéhez:

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

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 függvényt, amely tartalmazza az app.js alján található korábbi kódunkat is:

function init() {
  const savedAccount = localStorage.getItem(storageKey);
  if (savedAccount) {
    updateState('account', JSON.parse(savedAccount));
  }

  // Our previous initialization code
  window.onpopstate = () => updateRoute();
  updateRoute();
}

init();

Itt visszakeressü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 az oldalfrissítés során lehet, hogy van olyan kód, amely az állapotra támaszkodik.

Az Irányítópult oldalt is megtehetjük az alkalmazásunk alapértelmezett oldalának, mivel most már megőrizzük a fiókadatokat. Ha nem található adat, az irányítópult gondoskodik a Bejelentkezés oldalra történő átirányításról. Az updateRoute() függvényben cseréld ki az alapértelmezett return navigate('/login'); sort return navigate('/dashboard');-ra.

Most jelentkezz be az alkalmazásba, és próbáld meg frissíteni az oldalt. Az irányítópulton 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á!

Lépj az irányítópultra a test fiókkal, majd futtasd le ezt a parancsot egy terminálban egy új tranzakció létrehozásához:

curl --request POST \
     --header "Content-Type: application/json" \
     --data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
     http://localhost:5000/api/accounts/test/transactions

Most próbáld meg frissíteni az irányítópult oldalt a böngészőben. Mi történik? Látod az új tranzakciót?

Az állapot a localStorage-nak köszönhetően határozatlan ideig megmarad, de ez azt is jelenti, hogy soha nem frissül, amíg ki nem jelentkezel az alkalmazás Előadás utáni kvíz

Feladat

Valósítsd meg az „Új tranzakció hozzáadása” párbeszédablakot

Íme egy példakép az elkészült feladat eredményéről:

Példa az „Új tranzakció hozzáadása” párbeszédablakra


Felelősség kizárása:
Ez a dokumentum az AI fordítási szolgáltatás, a Co-op Translator segítségével lett lefordítva. 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.