Díky tomu, že jsem se v minulé lekci naučili pracovat se stavem, otvírají se nám v Reactu mnohé nové možnosti.

Formulářové prvky

Formulářové prvky jako textová polížka, zaškrtávací tlačítka apod. jsou jedním z hlavních způsobů, jak získat vstup o uživatele. V čístém JavaScritpu jsme zvyklí získávat hodnoty z těchto prvků tak, že je vybereme pomocí querySelector a použijme například vlastnost value.

const inputElm = document.querySelector('input');
const value = inputElm.value;

V Reactu však k DOM elementům na stránce přístup nemáme. Hodnotu uvnitř textového políčka se tak musíme uložit do stavu.

Představme si jednoduchou komponentu, kde uživatel zadá svůj věk.

const AgeField = () => {
  return (
    <label>
      Zadej svůj věk:
      <input type="text" />
    </label>
  );
};

Hodnotu uvnitř elementu input si chceme uložit do stavu pokaždé, když dojde k její změně. Vytvoříme si proto stav age a budeme jej měnit v reakci na událost onChange.

const AgeField = () => {
  const [age, setAge] = useState(null);

  return (
    <label>
      Zadej svůj věk:
      <input type="text" onChange={(e) => setAge(e.target.value)} />
    </label>
  );
};

Data binding

One-way (jednosměrný), two-way (obousměrný).

Cvičení - formulářové prvky

1

Registrace

to dáš
  1. Založte si novou React aplikaci podle klasického starteru

  2. Vytvořte komponentu App s jednoduchým textovým políčkem dle následujícího vzoru.

    const App = () => {
      const handleSubmit = (e) => {
        e.preventDefault();
      };
    
      return (
        <form onSubmit={handleSubmit}>
          <label>
            Uživatelské jméno:
            <input type="text" />
          </label>
          <button type="submit">Registrovat</button>
        </form>
      );
    };
    
  3. Na políčko přidejte událost onChange. V reakci na událost do konzole vypište obsah políčka pomocí vlastnosti target.value. Vyzkoušejte, že když do políčka píšete, v konzoli vidíte každou změnu jeho hodnoty.

  4. Uvnitř komponenty App vytvořte stav userName s výchozí hodnotou prázdný řetězec. Vytvořte obousměrný (two-way) data binding mezi textovým políčkem a stavem userName.

  5. V reakci na událost onSubmit do konzole vypište jméno uživatele uložené ve stavu userName.

  6. Na stránku přidejte div, který bude vidět pouze pokud ve stavu userName bude jméno a nikoliv prázdný řetězec. Obsahem prvku by měla být zpráva

    Registrován nový uživatel jaroslav
    

    Za jméno jaroslav dosaďte obsah stavu userName.

  7. Pokud je ve stavu userName uložen prádný řetězec, zobrazte ve vašem divu zprávu ve smyslu

    Uživatelské jméno je povinný údaj
    
  8. Vzpomeňte si na vlastnost disabled a zařiďte, aby registrační tlačítko bylo dostupné pouze v případě, že ve stavu userName není prázdný řetězec.

2

Výběr země

to dáš

Pokračujte v předchozím cvičení.

  1. Přidejte do vašeho formuláře rozbalovací nabídku select, která bude sloužit k výběru země, ze které uživatel pochází.

    <label>
      Země původu:
      <select>
        <option value="Chorvatsko">Chorvatsko</option>
        <option value="Česká republika">Česká republika</option>
        <option value="Polsko">Polsko</option>
        <option value="Slovenská republika">Slovenská republika</option>
      </select>
    </label>
    
  2. Vytvořte stav country, který bude sloužit k uložení hodnoty z vaší nabídky. Výchozí hodnotu stavu nastavte na Česká republika.

  3. Pomocí události onChange zařiďte one-way data binding mezi nabídkou select a stavem country.

  4. Zařiďte two-way data binding mezi nabídkou select a stavem country tak, aby nabídka zobrazovala výchozí hodnotu uloženou ve stavu.

  5. Zprávu po úspěšné registraci změňte na

    Registrován nový uživatel jaroslav ze země Polsko
    

    Ve zprávě zobrazte zemi, kteoru si uživatel při registraci vybral.

3

Podmínky registrace

to dáš

Pokračujte v předchozím cvičení.

  1. Přidejte do vašeho formuláře zaškrtávací políčko označené textem
    Souhlasím s obchodními podmínkami
    
  2. Zařiďte, aby se uživatel mohl registrovat pouze v případě, že zaškrtnul souhlas s obdchodními podmínkami.

Efekty

V mírně komplikovanějších React aplikacích brzy narazíme na potřebu zareagovat na určité situace, které nastávají během vykreslování (renderování) komponenty. Budeme chtít například spustit nějaký kód ve chvíli, kdy se komponenta poprvé objeví na stránce. Čas od času také budeme chtít v komponentě provést něco ve chvíli, kdy se změní hodnota v props nebo ve stavu. K tomuto nám v Reactu slouží takzvané efekty effects .

Efekty jsou v podstatě velmi podobné událostem. Ve chvíli, kdy uvnitř komponenty něco nastane, budeme chtít zavolat naši funkci. Jako příklad si vyrobíme jednoduchou aplikaci, která řiká, kdo má zrovna svátek.

import React from 'react';
import { render } from 'react-dom';
import './index.html';

const App = () => {
  return (
    <>
      <h1>Svátky</h1>
      <div className="nameday">Svátek má Jiří</div>
    </>
  );
};

render(<App />, document.querySelector('#app'));

Pokud bychom chtěli spustit kousek kódu ve chvíli, kdy se naše komponenta App objeví na stránce, použijeme funkci useEffect a té předáme námi vytvořenou funkci.

import React, { useEffect } from 'react';
import { render } from 'react-dom';
import './index.html';

const App = () => {
  useEffect(() => console.log('jsem tady'), []);

  return (
    <>
      <h1>Svátky</h1>
      <div className="nameday">Svátek má Jiří</div>
    </>
  );
};

render(<App />, document.querySelector('#app'));

Funkce useEffect má dva parametry. Prvním je funkce, která se má zavolat a druhý parametr říká, za jakých okolností se má naše funkce volat. Prázdné pole [] znamená, že se efekt spustí pouze ve chvíli, kdy se komponenta poprvé objeví na stránce.

Efekty a volání API

Pokud chceme v naší aplikaci zobrazovat data z nějakého API, musíme si tato data stáhnout pomocí nám již známé funkce fetch. Tuto funkci je nejlepší zavolat právě ve chvíli, kdy se naše komponenta poprvé objeví na stránce.

Naše poslední aplikace zatím zobrazovala, že svátek má Jiří. To je však pravda pouze jeden den v roce. Pojďme aplikace vylepšit tak, aby si stáhla aktuální jméno z API.

import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';
import './index.html';

const App = () => {
  const [name, setName] = useState('');

  useEffect(() => {
    fetch('https://api.abalin.net/today?country=cz')
      .then((resp) => resp.json())
      .then((json) => setName(json.data.namedays.cz)
  }, []);

  return (
    <>
      <h1>Svátky</h1>
      <div className="nameday">Svátek má {name}</div>
    </>
  );
};

render(<App />, document.querySelector('#app'));

V tomto případě jsme si do stavu ukládali pouze obyčejný řetězec. Naše data však budou často zobrazovat seznamy, takže budeme chtít mít ve stavu uložené nějaké pole.

http://worldtimeapi.org/api/timezone

Cvičení - Efekty a volání API

4

Pražský čas

to dáš
  1. Založte si novou React aplikaci podle klasického starteru

  2. Založte komponentu App a uvnitř vytvořte jednoduchý efekt, který se spustí pří prvním zobrazení komponenty. Uvnitř tohoto efektu zavolejte funkci alert a zobrazte vyskakovcí okno s nějakou zprávou.

  3. Přidejte do vaší komponenty stav datetime, jehož výchozí hodnota bude prázdný řetězec. Ve vašem efektu smažte volání alert a uložte do stavu nějaký čas jako řetězec ve formátu

    '2020-11-13T22:46';
    

    Zobrazte váš čas někde na stránce a vyzkoušejte, že váš efekt správně nastaví stav při prvním zobrazení komponenty.

  4. Upravte váš efekt tak, aby pomocí volání fetch získal aktuální datum a čas pro časovou zónu Europe/Prague. Hodnotu získáte na API endpointu

    http://worldtimeapi.org/api/timezone/Europe/Prague
    

    pod položkou datetime. Získanou hodnotu uložte do stavu a vyzkoušejte, že vaše aplikace funguje.

5

Výběr zóny

to dáš

Pokračujte v předchozím příkladu.

  1. Vložte do stránky formulář, ze kterého si uživatel může vybrat časovou zónu. Uvnitř formuláře použijte následující select.
    <select>
      <option value="America/New_York">New York</option>
      <option value="Europe/London">Londýn</option>
      <option value="Europe/Moscow">Moskva</option>
      <option value="Europe/Prague">Praha</option>
      <option value="Asia/Hong_Kong">Hong Kong</option>
      <option value="Asia/Jerusalem">Jeruzalém</option>
    </select>
    
  2. Vytvořte stav timezone a funkci handleTimezoneChange, která propojí stav s hodnotou uvnitř prvku select. Jako výchozí hodnotu pro tento stav zvolte Europe/Prague.
  3. Zařiďte, aby se váš efekt volal při každé změně stavu timezone. Uvnitř efektu zkunstruujte URL pro váš dotaz tak, aby server poslal data pro uživatelem vybranou časovou zónu.
  4. Vaše aplikace by měla fungovat tak, že když uživatel vybere z nabídky časovou zónu, rovnou se mu na stránce ukáže aktuální čas v této zóně.