Lekce 2 - Struktura projektu a životní cyklus aplikace
V předchozí lekci, Představení frameworku, jsme si popsali výhody mobilních aplikací, instalaci NodeJS a Android Studia a připravili si vývojové prostředí.
V dnešním tutoriálu vývoje multiplatformních mobilních aplikací v React Native se podíváme na strukturu React Native projektu a životní cyklus aplikace.
Vytvoření a struktura React Native projektu
Nový projekt si vytvoříme jednoduše pomocí spuštění příkazu v terminálu. Přesuneme se do složky, v níž chceme projekt mít. V terminálu zadáme:
npx create-expo-app PrvniProjekt
Nástroj npx jsme nainstalovali společně s Node.js. Tento příkaz
spouští balíčky npm, navíc dokáže spustit libovolný npm balíček, aniž
bychom tento balíček instalovali. PrvniProjekt
je pak vcelku
logicky název našeho prvního projektu. Podívejme se, jak vypadá struktura,
kterou jsme vytvořili.
Složka assets/
Do této složky patří obrázky, fonty, zvuky a další mediální soubory.
Složka node_modules/
Naše aplikace používá různé balíčky a knihovny. Ty jsou právě v
této složce a specifikovány jsou v souboru package.json
.
Složka .gitignore/
Složky a soubory v tomto souboru budou ignorovány při práci s verzovacím systémem Git. To se hodí, když chceme vyloučit určité části projektu z repositáře. Více informací o tomto populárním verzovacím systému máme v kurzu Git.
Soubor App.js
Toto je vstupní bod pro naši aplikaci. Soubor obsahuje hlavní komponentu, která se vyrenderuje při startu aplikace.
Soubor app.json
V tomto konfiguračním souboru najdeme nastavení jako zobrazované jméno, popis a různé specifikace pro jednotlivé platformy.
Soubor babel.config.js
Tento soubor konfiguruje JavaScript transkompilátor Babel. Definuje, jak by měl být náš JavaScript kód transformován, aby byl kompatibilní na zařízeních se staršími verzemi JavaScriptu. Takže kód se syntaxem ES5 a novější je překonvertován tak, aby mohl být spuštěn na zařízeních, které tyto funkce nepodporují.
Soubor package-lock.json
Soubor slouží k zaznamenávání konkrétních verzí závislostí a jejich podzávislostí, které jsou nainstalovány v našem projektu. Zajišťuje, že každý vývojář pracující na projektu používá stejné verze balíčků, což zabraňuje neočekávanému chování způsobenému nesouladem verzí.
Soubor package.json
Zde jsou všechna metadata, závislosti a skripty naší aplikace. Zmíněné skripty slouží například ke spuštění serveru nebo sestavení aplikace.
Životní cyklus React Native aplikace
V React Native nezáleží, jestli vytváříme aplikace pro Android nebo iOS, životní cyklus je stejný. Komponenta referuje na konkrétní část naší aplikace a definuje celý svůj život od vytvoření / zobrazení až do zavření / zrušení, čemuž říkáme životní cyklus komponenty. Tento cyklus zahrnuje několik etap a metod, které jsou volány při přechodu mezi těmito etapami. Důležité je si uvědomit, že každá samostatná část aplikace by měla být reprezentována svou vlastní komponentou. Například:
- když spustíme aplikaci, uvidíme první obrazovku s logem, což je reprezentováno první komponentou,
- poté zobrazíme základní menu (druhá komponenta),
- po kliknutí na odkaz v menu se otevře nová obrazovka (třetí komponenta) a tak dále.
Životní cyklus komponenty
Teď již víme, že existují komponenty, které mají své metody. Kdy a proč se ale které metody volají? Podívejme se na grafické znázornění:
Etapy komponenty
Život komponenty rozdělíme do čtyř fází:
Mounting fáze
Montáž neboli Mounting - jedná se o proces, kdy je komponenta vytvořena a připojena do DOMu, nebo v případě React Native do hierarchie komponent pro zobrazení na obrazovce. Během mountu komponenty dochází k volání čtyř metod:
Constructor()
: První z nich je konstruktor. Slouží k inicializaci komponent v původním stavu a k případnému nastavení stavu.getDerivedStateFromProps()
: Tato metoda pouze vrací objekt s aktualizovaným stavem.render()
: Toto je jediná vyžadovaná metoda v React komponentách. Metoda udává, co bude zobrazeno na obrazovce.ComponentDidMount()
: Tato metoda se volá potom, co komponenta dokončí vykreslovací část. Je dobrým zvykem načíst zde data ze vzdáleného koncového bodu, což vede k aktualizaci stavu a opětovnému vykreslení.
Updating fáze
Aktualizace neboli Updating - při aktualizaci dochází ke změně stavu dat a případnému překreslení komponent. Stejně jako u Mountingu i Updating má své metody. Pro optimalizaci výkonu se při updatu vytváří virtuální DOM, což je abstraktní reprezentace změn, které mají být provedeny na skutečném DOMu. Tím se minimalizuje počet změn, které musí být provedeny na straně uživatelského rozhraní. Kdykoliv se vyskytne nějaká změna ve stavu nebo props, začne aktualizační proces s následujícími metodami:
getDerivedStateFromProps()
: Jak jsme již uvedli, metoda vrací aktualizovaný objekt.- `shouldComponentUpdate(): Zde se rozhodne, jestli dojde k překreslení komponenty s novými daty. Ve většině případů chceme, aby vrácená hodnota byla true, což je i defaultní nastavení.
render()
: Metoda závisí na hodnotě z metodyshouldComponentUpdate()
.getSnapshotBeforeUpdate()
: Hlavním případem použití této metody je zachycení informací, které jsou potřebné k zachování některého aspektu uživatelského rozhraní nebo chování komponenty předtím, než se může změnit v důsledku nového vykreslení.componentDidUpdate()
: Tato metoda je volána ihned po dokončení vykreslování.
Unmounting fáze
Demontáž neboli Unmounting označuje proces, kdy je
komponenta odstraněna z DOMu a již není aktivní nebo viditelná na
obrazovce. To se obvykle děje tehdy, když uživatel opouští obrazovku, na
které byla komponenta zobrazena, nebo když je komponenta explicitně
odstraněna z hierarchie komponent. Tato fáze má pouze jednu metodu a to
componentWillUnmount()
. Ta se spustí, jakmile je komponenta
odstraněna z DOMu. Lze tak mj. zrušit probíhající network request.
Error Handling fáze
Ošetření chyb neboli Error Handling - kdykoliv se objeví nějaká chyba při vykreslování komponenty, jsou zavolány patřičné metody:
getDerivedStateFromError()
: Tato metoda je volána při aktualizaci stavu komponenty po zachycení chyby a slouží k aktualizaci stavu tak, aby komponenta mohla vykreslit nějaký alternativní obsah nebo informace o chybě.componentDidCatch()
: Používá se pro zachycení a zpracování chyb, které se vyskytnou uvnitř komponenty nebo u jejích potomků během procesu renderování.
Všechny výše uvedené metody jsou virtuální, tudíž je lze přepisovat a tím jim dodat vlastní logiku.
Spuštění aplikace
Aplikaci spustíme. Přesuneme se do složky PrvniProjekt/
a
otevřeme terminál. Do příkazové řádky zadáme:
npx expo start
Výstupem bude:
Spuštění aplikace C:\Users\karel\Documents\ITnetwork\react native\PrvniProjekt>npx expo start Starting project at C:\Users\karel\Documents\ITnetwork\react native\PrvniProjekt Starting Metro Bundler ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ █ ▄▄▄▄▄ █ ██▀▀ ▀▄▀█ ▄▄▄▄▄ █ █ █ █ █ ▀█ ▀█ ▄█ █ █ █ █ █▄▄▄█ █▀ █▄▀▀▄██ █▄▄▄█ █ █▄▄▄▄▄▄▄█▄█ ▀▄█ █▄█▄▄▄▄▄▄▄█ █▄ ▀▀ ▄▀▀█▄█▄█▄ ███ ▀▄▄ ▄█ █ █▀█ ▀▄▄█ ▄█▀▄█ ▀ █▄ ▀██ █▀ ████▄ █▀▄▀█▄▀▄▀▄▀▀▄ ▀██ ███ ▀ ▄▄ ▄█ ▄██▄▄▄█▄▀ ▀███ █▄▄██▄█▄█▀▄▀█▄▀▄▄ ▄▄▄ ▀ ▄▄█ █ ▄▄▄▄▄ █▀▀▀█▀██▀ █▄█ ▀▀▀██ █ █ █ █▄▀█▄ █▄█▄▄ ▄▄▀ ▀▀█ █ █▄▄▄█ █▀██ ▄██▄██▄▀█▀▀ ██ █▄▄▄▄▄▄▄█▄█████▄████▄▄▄▄▄▄█ › Metro waiting on exp://192.168.0.109:8081 › Scan the QR code above with Expo Go (Android) or the Camera app (iOS) › Using Expo Go › Press s │ switch to development build › Press a │ open Android › Press w │ open web › Press j │ open debugger › Press r │ reload app › Press m │ toggle menu › Press o │ open project code in your editor › Press ? │ show all commands
Spustíme Android Studio (první spuštění chvíli trvá kvůli stahování různých aktualizací). Vybereme New Project -> No Activity a Finish. Na ploše s novým projektem klikneme vpravo na Device Manager a pak na Pixel 7 Pro API 33. Klikneme na ikonu Play:
Tím se nám otevře Device Manager s diplejem telefonu:
Přesuneme se do otevřeného terminálu a zvolíme možnost a
.
Zobrazí se nám:
Propojení s Android Studiem: Logs for your project will appear below. Press Ctrl+C to exit. › Opening on Android... › Opening exp://192.168.0.109:8081 on Pixel_7_Pro_API_33 › Press ? │ show all commands
Tím máme aplikaci spuštěnou. Zatím sice nic neumí, ale na tom zapracujeme v dalších lekcích.
V příští lekci, Promises a asynchronní funkce, si popíšeme asynchronní funkce a promises a jejich využití.