NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 2 - Vykreslování v Reactu a jeho optimalizace

V předchozí lekci, Úvod do ekosystému Reactu, jsme si řekli něco o základech Reactu a představili jsme si jeho vybrané knihovny. Ukázali jsme si také, kde hledat informace o dostupných rozšířeních a podle čeho je vybírat.

V následujícím tutoriálu pokročilého Reactu se podíváme pod pokličku Reactu, abychom porozuměli, jak probíhá vykreslování. Napíšeme si k tomu krátkou aplikaci, na níž si proces vykreslování vysvětlíme. I když React je sám o sobě optimalizovaný pro rychlé vykreslování, existují techniky, které nám umožní ještě více zvýšit výkon našich aplikací. V druhé části tutoriálu se proto zaměříme na tři klíčové optimalizační techniky, konkrétně na memoizaci, lazy loading a virtualizaci.

Jak funguje vykreslování v Reactu

Vykreslování v Reactu je založeno na konceptu virtuálního DOM (Document Object Model). Na rozdíl od skutečného DOM, který představuje strukturu webové stránky v prohlížeči, je virtuální DOM lehkou, in-memory reprezentací skutečného DOM. React udržuje tuto virtuální reprezentaci a porovnává ji s aktuálním stavem DOM. Kdykoli dojde k změně v komponentě, React tuto změnu nejprve aplikuje na virtuální DOM, porovná starý a nový virtuální DOM, a pak efektivně aktualizuje skutečný DOM tím, že upraví jen ty části, které se skutečně změnily. Tento přístup pomáhá minimalizovat nákladné operace s DOMem a zvyšuje výkon aplikace.

Podívejme se na celý proces blíže:

  • Inicializace React aplikace - jakmile se aplikace poprvé načte, React vytvoří virtuální DOM podle její komponentové hierarchie.
  • Renderování - v momentu, kdy se změní stav nebo vstupní data aplikace, React vyvolá proces renderování. Každá komponenta ve stromě se renderuje do virtuálního DOM.
  • Porovnání s předchozím stavem - React porovná nový virtuální DOM s předchozím stavem virtuálního DOM. Tento krok se nazývá reconciliation (srovnání).
  • Vytvoření rozdílů (diffing) - React určí rozdíly mezi novým a starým virtuálním DOM. To jsou změny, které je třeba provést na skutečném DOM.
  • Aktualizace skutečného DOM - na základě rozdílů určených v předchozím kroku provede React aktualizaci na skutečném DOM.

Tento proces, jak jsme si už řekli, umožňuje Reactu rychle reagovat na změny a minimalizovat zbytečné aktualizace DOM, což vede k lepšímu výkonu.

Příklad vykreslování aplikace

Představme si nyní proces vykreslování na reálné aplikaci s následující komponentovou hierarchií:

Pokročilý React
  • Jakmile se načte React aplikace, začne se vykreslovat kořenová komponenta App.
  • Komponenta App vykreslí své dětské komponenty: Header, MainComponent a Footer.
  • Komponenta MainComponent vykreslí i své dítě MainCompChild.
  • Pokud dojde ke změně stavu v komponentě MainComponent, React v ní provede aktualizaci stavu.
  • React porovná nový virtuální DOM (po aktualizaci) s předchozím virtuálním DOM (po vykreslení).
  • React identifikuje rozdíly mezi novým a starým virtuálním DOM a určí, které části stránky byly změněny.
  • Nakonec React aktualizuje skutečný DOM pouze pro komponentu MainComponent a pro její dítě, MainCompChild.

Výsledek potom vypadá takto:

Pokročilý React

Aplikace ukazující vykreslování v praxi

Teorii už tedy známe a je na čase vyzkoušet si znalosti v praxi. Společně si tedy vytvoříme jednoduchou aplikaci, kde názorně uvidíme, jak vykreslování v Reactu funguje:

Pokročilý React

Založení projektu

V počítači si vytvoříme složku pro projekt a otevřeme si ji ve vybraném editoru kódu. Otevřeme si terminál a vytvoříme novou React aplikaci s názvem vykreslovani:

Založení projektu:
npx create-react-app vykreslovani

Pak změníme adresář na ten s novou aplikací (vykreslovani/) a spustíme lokální server na http://localhost:3000/:

Spuštění serveru:
cd vykreslovani
npm start

Příprava komponent

Naše kořenová komponenta je App.js. Kód, který bude obsahovat funkci App() v souboru App.js, vypadá takto:

function App() {
  console.log("aplikace")
  return (
    <div className="App">
     <h1>Aplikace</h1>
    </div>
  );
}

export default App;

V podobném duchu teď vytvoříme další komponenty ze stromu komponent. Každá komponenta obsahuje nadpis se svým názvem a také console.log s jasným identifikátorem, abychom pak v konzoli mohli sledovat vykreslování.

Záhlaví

Vytvoříme soubor Header.js s kódem:

function Header() {
    console.log("hlavicka")
  return (
    <div>
        <h2>Záhlaví</h2>
    </div>
  )
}

export default Header;

Hlavní komponenta

Vytvoříme soubor MainComponent.js s kódem:

import {useState} from 'react';
import MainCompChild from './MainCompChild';

function MainComponent() {
    console.log("hlavni komponenta");
    const [count, setCount] = useState(0);

    const incrementCount = () => {
        setCount((prevCount) => prevCount + 1); // Zvýší stav o 1 vzhledem k předchozímu stavu
      };

  return (
    <div style={{border: "2px solid"}}>
        <h2>Hlavní komponenta</h2>
        <p>Počet: {count}</p>
        <button onClick={incrementCount}>+</button>
        <MainCompChild />
    </div>
  )
}

export default MainComponent

Hlavní komponenta obsahuje jednoduché počítadlo, které po klikání na tlačítko se symbolem plus (+) připočítává k číslu jedničku. Dosahujeme toho pomocí změny stavu. Komponentě definujeme také border, ať vizuálně vidíme, že obsahuje také počítadlo a své dítě.

Do hlavní komponenty jsme si již importovali její dítě a také jej v ní vykreslujeme. Teď je čas dítě vytvořit v projektu.

Dítě hlavní komponenty

Vytvoříme si soubor MainCompChild.js s kódem:

function MainCompChild() {
    console.log("dite hlavni komponenty")
  return (
    <div>
        <h3>Dítě hlavní komponenty</h3>
    </div>
  );
}

export default MainCompChild;

Patička

No a na závěr si vytvoříme v projektu soubor Footer.js s kódem:

function Footer() {
    console.log("paticka")
  return (
    <div>
        <h2>Patička</h2>
    </div>
  )
}

export default Footer;

Tím máme všechny potřebné komponenty hotové.

Import do App.js a vykreslení komponent

Je tedy čas importovat všechny vytvořené komponenty do souboru App.js:

import Header from './Header';
import MainComponent from './MainComponent';
import Footer from './Footer';

Pod tag <h1> s nadpisem Aplikace pak vykreslíme importované komponenty:

<Header />
<MainComponent />
<Footer />

Sledování vykreslování v konzoli

Otevřeme si naši aplikaci v prohlížeči, klikneme pravým tlačítkem myši a otevřeme vývojářské nástroje. V nich přejdeme do konzole. Pokud je v konzoli již něco vypsané, smažeme ji. Následně obnovíme naši stránku. V konzoli se vypíši názvy všech našich komponent, protože se právě všechny iniciálně vykreslily:

Pokročilý React

Po kliknutí na tlačítko Plus se změní stav v hlavní komponentě. V konzoli hned vidíme, jak se opět vykreslí pouze tato hlavní komponenta a její dítě. To se opakuje po každém kliknutí na tlačítko:

Pokročilý React

Praktickou ukázku tedy máme za sebou a můžeme se pustit do slíbených optimalizačních technik.

Techniky optimalizace vykreslování

I když React vykonává vykreslování efektivně, existují situace, kdy můžeme jeho výkon ještě zlepšit.

Memoizace

Pomocí memoizace dokážeme uchovávat v paměti výsledky dřívějších výpočtů, čímž se vyhneme opakovanému výpočtu stejných hodnot. To je užitečné zejména v komponentách, které obsahují náročné výpočty. Jednou z nejběžnějších technik memoizace v JavaScriptu je použití tzv. memoizačních knihoven, jako je například memo z Reactu, nebo knihovna lodash.memoize.

V Reactu lze memo použít pomocí hooku useMemo(). Hook přijímá dvě hlavní věci: funkci a pole závislých hodnot. Funkce, kterou předáme useMemo(), pak provádí výpočet nebo operaci, kterou chceme memoizovat. Pole závislých hodnot potom obsahuje všechny hodnoty, které jsou relevantní pro výpočet. Pokud se některá z těchto hodnot změní, useMemo() znovu provede výpočet.

Hook vrací memoizovaný výsledek výpočtu. Tento výsledek se nezmění, pokud se nezmění závislé hodnoty, což umožňuje zabránit zbytečnému vykonávání výpočtů při každém renderování komponenty.

Zatímco hooky jako useMemo() se používají ve funkcionálních komponentách, pokud pracujeme s projektem, který má třídní komponenty, lze pro memoizaci použít nástroje jako shouldComponentUpdate nebo PureComponent.

Lazy loading

Lazy loading umožňuje načítat komponenty až tehdy, když jsou potřeba. Tím dokážeme zrychlit počáteční načítání aplikace.

Jedním z nejběžnějších případů použití lazy loading je líné načítání obrázků. Namísto toho, aby se všechny obrázky stáhly najednou, jsou obrázky stahovány až tehdy, když jsou viditelné na obrazovce. Lazy loading se používá také pro code splitting. To znamená, že části kódu se načítají až tehdy, když jsou potřeba. Také tímto způsobem lze zlepšit výkon aplikace, a to snížením objemu kódu, který se musí stáhnout při prvním načtení stránky.

Virtualizace

Virtualizace umožňuje efektivně zobrazovat a spravovat velké seznamy dat na webových stránkách. Místo toho, aby byla vytvořena a vykreslena každá položka seznamu, jako je to v klasickém přístupu, virtualizace načítá a vykresluje pouze viditelné položky. To zvyšuje výkon a snižuje paměťovou zátěž. Virtualizace se obvykle využívá právě v kombinaci s lazy loadingem, kde se položky seznamu načítají až tehdy, kdy jsou potřeba (například při posunu dolů nebo nahoru).

Se všemi zmíněnými technikami se v průběhu kurzu detailně seznámíme.

V následující lekci, Serverové renderování s Next.js, se budeme zabývat frameworkem Next.js a serverovým renderováním.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 11x (320.06 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
Úvod do ekosystému Reactu
Všechny články v sekci
Pokročilý React
Přeskočit článek
(nedoporučujeme)
Serverové renderování s Next.js
Článek pro vás napsala Laura Baluchová
Avatar
Uživatelské hodnocení:
19 hlasů
Aktivity