Lekce 1. - React - úvod

10.02.2021 Programování #react #programování

Úvodní lekce pro výuku React Step by Step.


Předpoklady

Než začnete s tímto výukovým programem React, ujistěte se, že máte:

  • Základní znalost HTML a CSS.
  • Základy JavaScriptu (objekt, pole, podmínky, atd.).
  • Znalost funkcí JavaScript ES6 (syntaxe třídy, funkce šipek, destrukce objektů atd.).

Postupně se budeme seznamovat s jednotlivými kroky a návaznostmi jako jsou základy javascriptu, scss apod.

V průběhu kurzu budeme vše směřovat k závěrečnému projektu, který bude představovat jednoduchou aplikaci pro ToDo list. Nové věci budou vždy vysvětleny na nezávislých příkladech.

Co je React?

React (někdy nazývaný React.js nebo ReactJS) je knihovna JavaScriptu pro vytváření rychlého a interaktivního uživatelského rozhraní. Vznikl na Facebooku v roce 2011 a umožňuje vývojářům vytvářet rozsáhlé webové aplikace nebo komplexní uživatelská rozhraní integrací malého a izolovaného fragmentu kódu.

Někdy se React kvůli svému chování a schopnostem často nazývá framework. Ale technicky je to knihovna.

Na rozdíl od jiných frameworků, jako je Angular nebo Vue, se často musí použít více knihoven.

React umožňuje vývojářům vytvářet komplexní uživatelské rozhraní z izolovaného fragmentu kódu, jak bylo uvedeno výše. Abychom lépe porozuměli Reactu, musíme začít přemýšlet v React Component.

Server vs prohlížeč 

Klasické server-side webovky jsou vcelku jednoduché. Server totiž nemusí udržovat žádný stav. Přijde mu požadavek od uživatele, poslepuje dohromady nějaké řetězce (část z nich načte třeba z databáze) a celé to pak pošle uživateli do prohlížeče, který to rozparsuje a sestaví DOM (Document Object Model - stromová reprezetace toho co vidíte v prohlížeči jako HTML stránku + metody, kterými se dá upravovat či procházet).

Interaktivní JS webovky, které běží v prohlížeči, jsou podstatně složitější. Chceme totiž po nich daleko více než od server-side aplikací. Chceme nabídnout daleko vyšší uživatelský zážitek. Je trochu zbytečné s každou akcí překreslovat celou stránku, když můžeme změny bleskově provádět pomocí funkcí DOMu a uživateli tak dopřát pohodlí, které zná z desktopových aplikací.

Zlý DOM 

DOM a JavaScript jsou dvě úplně rozdílné věci. Teoreticky by mohl být DOM upravován i jiným jazykem, ale v praxi prohlížeče nabízejí pouze JavaScript. DOM je obrovský moloch, práce s ním je pomalá a prohlížeče nejsou vždy jednotné v jeho implementaci. JavaScript pak často neprávem sklízí nenávistné komentáře, které by ale měly směřovat právě na DOM. Dnešní JavaScript je naopak velmi rychlý a vcelku lišácky navržený, což ostatně potvrzuje i to, že se rozšiřuje i do oblastí, kde má narozdíl od prohlížečů silnou konkurenci (node.js).

DOM navíc představuje jednu velkou globální proměnnou, což přímo svádí k tomu, abychom ho používali jako místo pro ukládání stavu naší aplikace. Asi nemusím popisovat proč jsou globální proměnné zlo. U DOMu to pak ještě zhoršuje jeho pomalost. Stav aplikace bychom tedy měli udržovat jinde - v našem JavaScriptu a do DOMu šahat, jenom když je to skutečně potřeba. Pouze do něj zrcadlit změny z našeho JS kódu. Jenže jak to jednoduše udělat?

Koncept virtuálního DOM

DOM (Document Object Model) je rozhraní, které umožňuje JavaScriptu nebo jiným skriptům číst a manipulovat s obsahem dokumentu (v tomto případě dokumentu HTML).

Kdykoli se dokument HTML načte do prohlížeče jako webová stránka, vytvoří se pro tuto stránku odpovídající objektový model dokumentu. Jedná se jednoduše o objektovou reprezentaci HTML.

Tímto způsobem se JavaScript může připojit a dynamicky manipulovat s DOM, protože dokáže číst a porozumět jeho objektově založenému formátu. To umožňuje přidávat, upravovat obsah nebo provádět akce na webových stránkách.

Ale pozor! Nastal problém. Ačkoli ne s DOM. Pokaždé, když se DOM změní, prohlížeč bude muset přepočítat CSS, spustit rozložení a překreslit webovou stránku.

A s aplikací Single Page Application (SPA), kdy JavaScript aktualizuje DOM mnohem více, než musí. Věci se zpomalí kvůli procesu v pracovním postupu prohlížeče po manipulaci s DOM.

Potřebujeme tedy způsob, jak minimalizovat čas potřebný k překreslení obrazovky. To je místo, kde přichází virtuální DOM.

Jak název napovídá, jedná se o virtuální reprezentaci skutečného DOM. Využívá strategii, která aktualizuje DOM, aniž by bylo nutné překreslovat všechny prvky webové stránky. Tím je zajištěno, že skutečný DOM obdrží pouze data potřebná k překreslení uživatelského rozhraní.

Podívejme se, jak to funguje. Kdykoli se do uživatelského rozhraní přidá nový prvek, vytvoří se virtuální DOM. Pokud se nyní stav tohoto prvku změní, React podruhé znovu vytvoří virtuální DOM a porovná s předchozí verzí, aby zjistil, který z objektů virtuálního DOMu se změnil.

Poté aktualizuje POUZE objekt na skutečném DOM. To je zásadní optimalizace, protože snižuje náklady na výkon při opětovném vykreslení webové stránky.

Myšlení v komponentách

Při vytváření aplikace s Reactem se vytváří spoustu nezávislých, izolovaných a opakovaně použitelných komponent. Představme si komponentu jako jednoduchou funkci, kterou můžeme zavolat pomocí nějakého vstupu a ten vykreslí nějaký výstup.

A protože můžeme znovu použít funkce, můžeme také znovu použít komponenty, sloučit je a vytvořit tak komplexní uživatelské rozhraní.

Podívejme se na obrázek níže. Je to jednoduchá aplikace pro zadávání úkolů.

components

Chceme-li vytvořit tento typ aplikace React nebo jakékoli složité aplikace, první věcí, kterou musíme udělat, je rozdělit a rozložit design uživatelského rozhraní na menší a izolovanou jednotku, jak je uvedeno na obrázku.

Každou z těchto jednotek lze reprezentovat jako komponentu, kterou můžeme sestavit izolovaně a později sloučit a vytvořit úplné uživatelské rozhraní.

Nadřazená komponenta (známá také jako kořenová komponenta), ToDoContainer, obsahuje všechny ostatní komponenty (známé jako podřízené komponenty). Položka Header představuje obsah záhlaví. Komponenta InputToDo přijímá vstup uživatele. Komponenta ToDosList je seznamem úkolů. ToDoItem komponenta se stará o každou položku ze seznamu a nakonec Navbar se stará o navigaci.

Jak vidíme v pohledu a z rozpisu budeme vytvářet šest různých komponent izolovaně. I když později přidáme další komponentu, až se začneme učit směrování v React. Tam vykreslíme jedinou stránku About.

Pokud chceme, můžeme dále rozložit ToDoItem na menší součásti - jednu se zaškrtávacím políčkem, druhou s úkolem todos a druhou s tlačítkem pro odstranění. Možná budeme chtít mít menší komponenty v závislosti na tom, jak si prohlížíte design. V ideálním případě by se komponenta měla postarat o jednu funkčnost.

Nastavení pracovního prostředí

Existuje několik způsobů, jak můžeme komunikovat a začít s Reactem. Ačkoli React doporučuje nastavení prostředí pomocí create-react-app nástroje CLI, lze začít pracovat s Reactem jednoduchým napsáním kódu do souboru HTML.

To vás rychle uvede do provozu a nevyžaduje žádnou instalaci.

Psaní Reactu přímo v HTML

Tato metoda interakce s React je nejjednodušší způsob a je velmi snadná, pokud jste někdy pracovali s HTML, CSS a JavaScript.

Budeme mít soubor HTML, do kterého načteme tři skripty v elementu head ukazující na jejich příslušné CDN - ReactReactDOM Babel.

Poté vytvoříme prázdný element div a dáme z něj id of root. Zde bude aplikace pracovat. Nakonec vytvoříme element script, do kterého napíšeme svůj React kód.

Soubor index.html by měl vypadat takto:

Oblast na, kterou se zaměříme v kódu je element script. Atribut type v úvodním tagu je povinná pro použití Babel . Ve skriptu máme něco, co vypadá jako HTML.

const element = <h1>Hello from React</h1>

A možná vás zajímá, proč píšeme HTML uvnitř JavaScriptu. Nejedná se o HTML, ale JSX.

Co je JSX?

Psaní kódu JavaScript / React k popisu toho, jak bude uživatelské rozhraní (UI) vypadat, není tak jednoduché, jak se možná zdá. Díky tomu autor React vytvoří něco, co vypadá jako JavaScriptová verze HTML. Toto se nazývá JSX (JavaScript XML). Jedná se o rozšíření syntaxe XML podobné JavaScriptu, které usnadňuje a intuitivněji popisuje uživatelského rozhraní.

Pod kapotou je JSX za běhu překládán do běžné verze JavaScriptu, protože jej prohlížeč nedokáže přečíst. Funguje to takto:

Kód JSX je předán Babelu (kompilátoru JavaScriptu), který jej poté převede na prostý kód JavaScript, kterému bude rozumět každý prohlížeč. Tento kompilátor také mění všechny funkce JavaScriptu ES6 na to, co by starší prohlížeče rozpoznaly. Například převede klíčové slovo const na var.

Přejděte na web babel a přidejte kód JSX do editoru Babel.

babelrepl

Měli bychom vidět něco podobného jako na obrázku výše. Nyní se podívejme na to, co je na pravé straně editoru Babel. Kód JSX se převede na prostý kód React. Zde můžeme dojít k závěru, že použití JSX k popisu toho, jak vypadá uživatelské rozhraní, je mnohem jednodušší.

Nezapomeňte také, že jsme načetli knihovnu React v hlavě našeho kódu HTML, i když ji výslovně nepoužíváme. Ale pod kapotou React používá objekt React z knihovny, jak můžeme vidět také na pravé straně editoru.

Vezměme na vědomí následující informace o JSX

  • Můžeme použít platný JavaScript výraz uvnitř JSX pomocí složených závorek, {}.
  • V JSX jsou atributy prvků obslužné rutiny událostí vždy ve složených závorkách. Několik výjimek je aria-* data-* atributů, které jsou malé.

V našem prvním příkladu vidíme, že se nic nezobrazuje. Ale pokud otevřeme konzolu (protože používáme v našem kódu prvek console.log), uvidíme objekt představující JSX.

Výstupem je prvek React, který představuje objekt Virtual DOM. Představme si to jako plán skutečného objektu DOM. Díky tomu je ReactJS velmi snadné vytvářet, manipulovat a aktualizovat.

Nyní si představme, že máme na obrazovce seznam těchto JSX (tj. Objektů Virtual DOM). Pak se z JSX aktualizuje. React by znovu vytvořil zcela nový seznam objektů stále ve Virtual DOM a porovnal by je s předchozí verzí, aby zjistil, který z virtuálních DOM objektů se změnil. Tento proces se nazývá diffing.

Poté React osloví skutečný DOM a aktualizuje pouze změněný objekt.

Pojďme vykreslit prvek React uvnitř skutečného DOM, abychom ho viděli. Aktualizujme script prvek tak, aby vypadal takto:

Nyní byste měli vidět obsah na obrazovce.

Co se děje?

Ve skriptu se nachází metoda render(), kterou React vystavuje prostřednictvím objektu ReactDOM k vykreslení prvku React do DOM.

Určitě si pamatujte, že jsme knihovnu ReactDOM jsme připojili do hlavičky souboru HTML. Jinak by metoda render() nefungovala.

První argument metody render() definuje, co chceme vykreslit, zatímco druhý definuje, kam ji chceme vykreslit. Jak je vidět v kódu, k odkazování na element div uvnitř prvku body používáme obyčejný JavaScript .

Lze říci, že JSX zápis lze interpretovat jako React.createElement(). Tímto způsobem lze zapisovat JS kód bez nutnosti použití dalších knihoven.

Jak by to vypadalo bez JSX?

Příklady zápisu:

<h1>Hello Word</h1>

zapíšeme jako

React.createElement('h1', null, 'Hello World')

Zápis s atributy

<div onClick={this.props.clickHandler} data={this.state.data}>
  Click Me!
</div>

se zapíše

React.createElement('div', {
                      'onClick': this.props.clickHandler, 
                      'data': this.state.data
                    }, 
                    'Click Me!')

Vnořené prvky

<div>
  <h1>Hello World</h1>
  <a>Click Me!</a>
</div>

se interpretují

React.createElement('div', null, 
  React.createElement('h1', null, 'Hello World')
  React.createElement('a', null, 'Click Me!')
)

Přestože jsou výše uvedeny příklady, ve kterých je JS kód zapisován přímo do HTML souboru, tak v reálných projektech se využívá toho, že se JS kód rozděluje do samostatného souboru, který se pak do stránky připojuje. Takže vše co je ve značkách < script > ... < /script > se může umístit například do souboru apps.js.

GitHub

Obsah souboru apps.js obsahuje veškerý kód, který byl mezi značkami < script > ... < /script >

GitHub

Všimněte si, že značky pomocí, kterých je připojený soubor apps.js obsahují atribut type=text/babel. Pokud by tento atribut nebyl přidán, tak při využití JSX by skript hlásil chybu.

Ještě jednou proč JSX?

React zahrnuje skutečnost, že logika vykreslování je neodmyslitelně spojena s jinou logikou uživatelského rozhraní: jak jsou události zpracovávány, jak se stav mění v průběhu času a jak jsou data připravena k zobrazení.

Místo toho, aby docházelo k oddělení  technologie od značek do samostatných souborů, React rozděluje do souborů tzv. komponenty, které obsahují obojí.

React sice nevyžaduje použití JSX, ale většina programátorů to považuje za užitečné, jako vizuální pomůcka při práci s UI uvnitř kódu JavaScriptu. React rovněž umožňuje zobrazovat další užitečné chybové a varovné zprávy.

Používání výrazů v JSX

V níže uvedeném příkladu, je nadeklarována proměnná pod názvem name, na kterou se v JSX odkazujme pomocí složených závorek.

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

ReactDOM.render(
  element,
  document.getElementById('root')
);

Do složených závorek v JSX můžeme vložit libovolnou proměnnou. Například 2 + 2, user.firstName nebo formatName(user).

V příkladu níže je volána JS funkce formatName(user), která vypíše výsledek do tagu H1.

JSX je spíše výrazem

Po kompilaci se výrazy JSX stávají běžnými funkcemi JavaScriptu a vyhodnocují se na objekty jazyka JavaScript. To znamená, že JSX můžeme použít uvnitř příkazů if nebo for, přiřadit je k proměnným, přijmout jako argumenty a vrátit je z funkcí:

function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

Specifikace atributů v JSX

Pro běžné řetězce a atributy, můžeme použít uvozovky:

const element = <div tabIndex="0"></div>;

Pro vložení výrazu JavaScriptu v atributu, použijeme složené závorky:

const element = <img src={user.avatarUrl}></img>;

Při vkládání výrazu jazyka JavaScript do atributu, neumisťujte uvozovky kolem složených závorek. Měli byste buď použít uvozovky (pro řetězcové hodnoty) nebo složené závorky (pro výrazy), ale ne oba ve stejném atributu.

Varování:
Vzhledem k tomu, že JSX je blíže k JavaScriptu než ke kódu HTML, React DOM používá camelCase namísto názvů atributů HTML v konvenci pojmenování vlastností. Například JSX class se stává className tabindex se stává tabIndex.

Potomci v JSX

Pokud je značka prázdná, můžeme ji okamžitě zavřít />, stejně jako v XML:

const element = <img src={user.avatarUrl} />;

Značky JSX mohou obsahovat potomky:

const element = (
  <div>
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);

Prevence injenktážních útoků v JSX

Pro bezpečné vložení uživatelských vstupů v JSX:

const title = response.potentiallyMaliciousInput;
// This is safe:
const element = <h1>{title}</h1>;

Ve výchozím nastavení React DOM escapuje před přidáním všechny hodnoty vložených do JSX. Tím zajistíte, že se nikdy nic nemůžete injektovat, co není výslovně napsáno ve vaší aplikaci. Všechno je před vykreslením převedeno na řetězec. Pomáhá to předcházet útokům XSS (skriptování mezi jednotlivými servery).

JSX představuje objekty

Babel kompiluje JSX na volání React.createElement()

Tyto dva příklady jsou totožné:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

React.createElement() provádí několik kontrol, které pomohou psát chybový kód, ale v podstatě vytváří objekt, jako je tento:

// Note: this structure is simplified
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
  }
};

Tyto objekty se nazývají "prvky React". Můžeme si je představit jako popis toho, co chceme vidět na obrazovce. React čte tyto objekty a používá je k sestavení DOM a udržuje ji aktuální.

V čem programovat React?

Pro vývoj aplikací v React lze použít celou řadu editorů. Komplexní řešení nabízí některý z produktů společnosti JBrean jako je WebStorm nebo PhpStorm.

Jednodušší a pro začátek plně dostačující je Visual Studio Code, který nabízí celou řadu modulů, které lze do editoru nainstalovat a poskytují adekvátní alternativu.

Visual Studio Code

  1. Stažení editoru - https://code.visualstudio.com/download
  2. Pro provoz React skriptů je vhodné nainstalovat plugin Live Server.
  3. Otevřete adresář, kde se nachází uložené soubory Reactu. 
  4. Po napsání kódu klikněte pravým tlačítkem myši na kódu a zvolte položku Open with Live Server.
  5. Dojde k zobrazení portu, na kterém se zavolá adresa lokálního serveru v prohlížeči, např. http://localhost:5500