IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 5 - Stavy v Reactu a hook useState()

V minulé lekci, Vlastnosti v React - Props, jsme si vysvětlili koncept vlastností props. Ukázali jsme si, jak se vlastnosti zadávají v HTML kódu, načítají v komponentě a destrukturalizují.

V tomto React tutoriálu se naučíme obsluhovat stavy naší aplikace, objevíme React hooks a naučíme se používat hook useState().

Stavy v React a hooks

Stav React komponent (state) je podobný vlastnostem, ale používá se pouze uvnitř komponenty a může se měnit. V podstatě se jedná o privátní data komponenty pouze pro vnitřní použití.

Stavy jsou jinými slovy proměnné, které se v React aplikaci mění a my na jejich změnu chceme nějak reagovat.

Hooks

React hooks - Základy React

Jak jsme již nastínili v úvodní lekci, k funkcionalitám Reactu se dostáváme pomocí hooks. Hook (v překladu háček) není nic jiného, než funkce, která nám zpřístupní nějakou funkcionalitu z React. "Zasekneme" se háčkem do Reactu a "taháme" si, co potřebujeme. Pro práci s vnitřním stavem komponenty budeme používat hook (funkci) useState().

Práce s hookem useState()

Použití useState() probíhá ve třech krocích:

1. Hook musíme prvně naimportovat, abychom měli funkci useState() dostupnou:

import React, { useState } from 'react';

2. Zavoláme useState() a předáme mu výchozí hodnotu stavu (ta může být i null):

useState(null);

3. Funkce useState() nám vrátí pole se dvěma proměnnými, kde první proměnná obsahuje současný stav a druhá proměnná je funkce pro změnu tohoto stavu:

const [stav, setStav] = useState(null);

Proměnná stav nyní obsahuje stav s hodnotou null. A pomocí funkce setStav() tento stav můžeme měnit. Stejným způsobem si můžeme v komponentě vytvořit další stavy. Pojďme si tento jednoduchý mechanismus vyzkoušet na příkladu.

Vytvoření projektu - Tlačítko s poštovní schránkou

Pro vyzkoušení stavů si vytvoříme projekt, ve kterém bude tlačítko s poštovní schránkou. Jakmile na něj klikneme, schránka se otevře a po opětovném kliknutí se zase zavře. K reprezentaci stavu schránky použijeme stav.

V průzkumníku Windows klikneme pravým tlačítkem myši na naši složku s projekty za držení klávesy Shift. V kontextovém menu vybereme otevření nového okna Terminal/Power­Shell:

Kontextové menu pro spuštění příkazového řádku - Základy React

Pomocí následujícího příkazu vytvoříme nový React projekt s názvem mailbox:

Windows PowerShell
PS C:\Users\sdrac\Dropbox> npx create-react-app@^5.0.1 mailbox

Pomocí příkazu cd se přesuneme do složky projektu:

Windows PowerShell
PS C:\Users\sdrac\Dropbox> cd mailbox

A projekt spustíme příkazem:

Windows PowerShell
PS C:\Users\sdrac\Dropbox\mailbox> npm start

Následně se přesuneme opět do Průzkumníku Windows, klikneme na složku mailbox/ pravým tlačítkem myši a otevřeme ji ve VS Code pomocí nabídky Otevřít v Code.

Komponenta MailboxButton

Ve složce src/ si vytvoříme nový soubor MailboxButton.js. Do něj vložíme následující základ komponenty:

function MailboxButton() {
    return <button>📪</button>;
}

export default MailboxButton;

Soubor uložíme. Pro obrázek poštovní schránky jsme použili emoji, abychom jej nemuseli stahovat 🤩 Trochu si jej ještě zvětšíme přidáním CSS stylu do App.css:

button {
  margin-top: 5rem;
  font-size: 10rem;
}

Soubor opět uložíme.

Vložení komponenty do App.js

Z komponenty App.js odstraníme nepotřebné součásti výchozího React projektu. Dále naimportujeme naši komponentu MailboxButton a vložíme ji do HTML kódu komponenty App:

import './App.css';
import MailboxButton from './MailboxButton';

function App() {
  return (
    <div className="App">
      <MailboxButton />
    </div>
  );
}

export default App;

Soubor uložíme a můžeme se podívat do prohlížeče, kde uvidíme naše tlačítko:

React App
localhost:3000

Přidání stavu

Do komponenty si nyní naimportujeme hook useState() a jeho zavoláním si definujeme stav pro to, zda je poštovní schránka plná:

import React, { useState } from 'react';

function MailboxButton() {
    const [full, setFull] = useState(false); // vytvoření stavu full

    return (
        <button>
            {full ? '📬' : '📪'}
        </button>
    );
}

export default MailboxButton;

Pomocí funkce useState() jsme vytvořili dvě proměnné:

  • full - Stav určující, zda je poštovní schránka plná.
  • setFull() - Setter funkce pro změnu stavu poštovní schránky.

Při volání useState() jsme zároveň nastavili, že výchozí stav je false.

Rovněž jsme upravili vykreslení tlačítka. To je nyní rozepsané na více řádek, což způsobilo, že jsme celé JSX museli vložit do závorek (). Do tlačítka vykreslujeme buď emoji plné poštovní schránky 📬 nebo prázdné 📪 podle toho, zda je stav full true nebo false. Použili jsme ternární operátor v JSX, kdy se při pravdivé hodnotě proměnné vykreslí část za otazníkem ? a při nepravdivé část za dvojtečkou :. Určitě jej znáte i z JavaScriptu.

V prohlížeči si můžeme zkontrolovat, že aplikace dělá stále to samé. Můžete si zkusit změnit výchozí stav v parametru funkce useState() z false na true, čímž se změní obrázek na schránce:

React App
localhost:3000

Změna stavu

Nyní elementu <button> obsloužíme událost onClick. K tomu si vytvoříme funkci uvnitř komponenty s názvem začínajícím na handle*, v našem případě handleClick():

import React, { useState } from 'react';

function MailboxButton() {
    const [full, setFull] = useState(false);

    function handleClick() {
        setFull(!full);
    }

    return (
        <button onClick={handleClick}>
            {full ? '📬' : '📪'}
        </button>
    );
}

export default MailboxButton;

Ve funkci nastavíme pomocí setteru setFull() novou hodnotu stavu a to na negaci stavu původního, tedy !full. Funkci také nastavíme do atributu onClick elementu <button>. Soubor uložíme a můžeme si v prohlížeči vyzkoušet, že schránka po kliknutí opravdu mění svůj stav a zobrazuje jiný emoji:

Poštovní schránka - Základy React

Vzhled emoji se bude lišit dle vašeho operačního systému.

Proč nepoužijeme proměnné?

Možná vás napadlo, proč používat nějaké stavy, když můžeme stejně dobře vytvořit jen obyčejnou true/false proměnnou, která by stav poštovní schránky určovala? Stavy mají navíc vnitřní logiku, kterou pak využívá vykreslovací jádro React. Používáním stavů se při jejich změně daná součást komponenty sama překreslí, aniž bychom se o to museli starat. Všimněte si, že jsme při kliknutí na tlačítko jeho obsah jinak neměnili, změnili jsme jen stav. To by s obyčejnou proměnnou nefungovalo.

Alternativní zápisy

Nakonec si opět ukažme několik alternativních zápisů, abyste uměli číst další aplikace.

Použití arrow funkce

K obsluze události můžeme použít arrow funkci, čímž se vyhneme deklaraci handler funkce:

import React, { useState } from 'react';

function MailboxButton() {
    const [full, setFull] = useState(false);

    return (
        <button onClick={() => setFull(!full)}>
            {full ? '📬' : '📪'}
        </button>
    );
}

export default MailboxButton;

Používání arrow funkcí při renderování v React způsobí, že se při každém překreslení vytvoří nová funkce. U složitějších projektů může být proto z hlediska výkonu lepší použít klasickou handler funkci.

Co ale nefunguje je zavolání setteru přímo v parametru bez arrow funkce:

import React, { useState } from 'react';

function MailboxButton() {
    const [full, setFull] = useState(false);

    return (
        <button onClick={setFull(!full)}>
            {full ? '📬' : '📪'}
        </button>
    );
}

export default MailboxButton;

Tím bychom totiž přes JSX setter rovnou zavolali (bez kliknutí na tlačítko). A React má ochranu před tím, aby změny stavů probíhaly bezprostředně za sebou, čímž se může aplikace zacyklit. Aplikace nám pak spadne s chybou: "Too many re-renders. React limits the number of renders to prevent an infinite loop":

Too many re-renders v React - Základy React

Stejnou chybu bychom dostali, kdybychom se snažili např. nastavit stav přímo v metodě komponenty, tedy aby se hned po nastavení zas změnil:

import React, { useState } from 'react';

function MailboxButton() {
    const [full, setFull] = useState(false);
    setFull(true); // Tento řádek způsobí chybu

    return (
        <button onClick={() => setFull(!full)}>
            {full ? '📬' : '📪'}
        </button>
    );
}

export default MailboxButton;

Dvě nejdůležitější součásti React aplikací, vlastnosti a stavy, máme tímto probrané :)

V následujícím cvičení, Řešené úlohy k 1.-5. lekci React, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

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 24x (177.05 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
Vlastnosti v React - Props
Všechny články v sekci
Základy React
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 1.-5. lekci React
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
92 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity