2

Podmíněné zobrazení

Naučíme si jak sestavovat CSS třídy a jak se rozhodnout, kterou část JSX chceme zobrazit.

Ve vanilla JavaScriptu jsem se nejdříve učili vytvářet statický obsah stránky a později jsme postupně přidávali interaktivitu. V Reactu budeme postupovat stejně. V této lekci uděláme další krok k tomu, aby naše stránky mohly být dynamičtější. Bude se nám k tomu hodit jedna hezká pomůcka z čistého JavaScriptu, kterou jsem v předešlých lekcích vynechali.

Ternární operátor

Představte si situaci, kdy chceme uživateli zobrzit jednoduchou zprávu podle jeho věku.

let message = null;
if (age >= 18) {
  message = 'Smíš vstoupit';
} else {
  message = 'Utíkej za mamkou';
}

Tato podmínka vypadá velmi přímočaře. Má však určité nevýhody.

  1. Jde o celkem dlouhý kód pro velmi jednoduchou věc.
  2. Musíme požívat proměnnou let, čemuž se snažíme co nejvíce vyhýbat.

JavaScript nám pro tuto situaci nabízí zkraktu, které se říká operátor pro podmíněný výraz conditional operator .

const message = age >= 18 ? 'Smíš vstoupit' : 'Utíkej za mamkou';

Tento operátor se dá použít vždy, když chceme do nějaké proměnné uložit různé hodnoty na základně nějaké podmínky.

V Reactu se nám tento operátor bude hodit ve více situacích. První z nich je situace, kdy chceme zkonstruovat název CSS třídy podle nějaké podmínky. Vezměme položku nákupního seznamu napsanou jako React komponentu.

const ShoppingItem = (props) => {
  return (
    <div className="item">
      <span className="item__name">{props.name}</span>
      <span className="item__amount">{props.amount}</span>
    </div>
  );
};

Dejme tomu, že chceme být schopni položku vysvítit jako vybranou. Můžeme tedy komponentě přidat novou prop s názvem selected a použít ji takto.

<ShoppingList name="jablka" amount="1 kg" selected={true} />

Budeme pak mít CSS třídu item--selected, která například nastavuje jinou barvu pozadí. Vybraná položka by tak měla mít atribut className nastaven takto.

<div className="item item--selected">

Obsah atributu className tedy chceme zkonstruovat dle hodnoty props.selected. To bychom mohli udělat pomocí podmínky.

const ShoppingItem = (props) => {
  let itemClass = null;
  if (props.selected) {
    itemClass = 'item item--selected';
  } else {
    itemClass = 'item';
  }

  return (
    <div className={itemClass}>
      <span className="item__name">{props.name}</span>
      <span className="item__amount">{props.amount}</span>
    </div>
  );
};

Díky podmíněnému operátoru si situaci můžeme zjednodušit takto.

const ShoppingItem = (props) => {
  const itemClass = props.selected ? 'item item--selected' : 'item';

  return (
    <div className={itemClass}>
      <span className="item__name">{props.name}</span>
      <span className="item__amount">{props.amount}</span>
    </div>
  );
};

Dokonce bychom hodnotu ani nemuseli ukládat do proměnné a použít podmíněný operátor přímo na místě.

const ShoppingItem = (props) => {
  return (
    <div className={props.selected ? 'item item--selected' : 'item'}>
      <span className="item__name">{props.name}</span>
      <span className="item__amount">{props.amount}</span>
    </div>
  );
};

Takovýto kód už však může být hůře čitelný, takže je dobré jej používat s mírou a uvážením.

Předávání hodnot pomocí props

Všimněte si, jak jsme použili naši komponentu ShoppingItem a jak jsme jí předali prop selected.

<ShoppingItem name="jablka" amount="1 kg" selected={true} />

Kdybychom to udělali takto

<ShoppingItem name="jablka" amount="1 kg" selected="true" />

ve vlastnosti props.selected uvnitř komponenty bychom měli řetězec 'true'. Pokud totiž předáváme hodnoty pro props pomocí uvozovek jako jsme zvyklí z HTML, uvnitř komponenty vždy obdržíme tyto hodnoty jako řetězce. Pokud chceme skutečnou boolean hodnotu true nebo false, musíme si pomocí složených závorek otevřít JavaScriptové okénko. Toto platí i pro ostatní hodnoty. Pokud chceme předat pomocí props číslo, provedeme to opět pomocí složených závorek.

<ShoppingItem name="jablka" amount={3} selected="true" />

Malinko nepřehledná situace nastane, pokud takto předáváme objekty, protože pak máme vedle sebe dvě složené závorky, kde každá znamená něco jiného.

<ShoppingItem name="jablka" amount={{ value: 3, unit: 'kg' }} selected="true" />

Vnější pár složených závorek otvírá JavaScript okénko uvnitř JSX a vnitřní pár vytváří objekt. Tento styl zápisu potkáme v druhé části lekce, kdy budeme nastavovat naším komponentám CSS styly.

Předávání hodnoty true

Poslední trik, kterým si ulehčujeme práci možná znáte již z HTML. Pokud chceme nějaké prop nastavit hodnotu true jako v tomto kódu

<ShoppingItem name="jablka" amount="1 kg" selected={true} />

stačí napsat pouze název dané prop a React už si domyslí, že do ní chceme vložit hodnotu true. Můžeme pak psát prostě

<ShoppingItem name="jablka" amount="1 kg" selected />

Cvičení: Podmíněné výrazy

1

Podmíněné jednohubky

to dáš

Přepište následující úryvky kódu tak, aby místo podmínek používaly operátor pro podmíněný výraz. Pracujeme v čistém JavaScriptu, takže není potřeba zakládat React projekt.

  1. const password = prompt('Zadejte heslo:');
    let valid = null;
    if (password.length > 8) {
      valid = 'Heslo je v pořádku';
    } else {
      valid = 'Heslo není bezpečné';
    }
    
  2. const grade = prompt('Počet bodů z písemky:');
    let passed = null;
    if (grade >= 50) {
      passed = '<span>prošel</span>';
    } else {
      passed = '<span class="red">neprošel</span>';
    }
    
2

React žárovka

to dáš

Vzpomeňte si na naše cvičení z vanilla JavaScriptu, kdy jsme rozsvěcovali a zhasínali žárovku. Zkusíme naši žárovku zprovoznit v Reactu.

  1. Založte si React projekt dle šablony z předchozí lekce.

  2. Stáhněte si zadaní obsahující připravené styly pro rozsvícenou i zhasnutou žárovku.

  3. Ve vašem React projektu vytvořte komponentu Bulb a nastylujte ji podle vzoru ze zadání.

  4. Chceme zařídit, že pokud komponentu použijeme takto

    <Bulb on={false} />
    

    zobrazí se zhasnutá žárovka. Pokud ji naopak použijeme takto

    <Bulb on={true} />
    

    nebo prostě takto

    <Bulb on />
    

    žárovka se zobrazí rozsvícená. Kýženého chování dosáhnete tak, že sestavíte obsah atributu className pomocí podmíněného operátoru z závislosti na hodnotě v prop on.

  5. Vložte na vaši stránku dvě zhasnuté a dvě rozsvícené žárovky.

Stylování JSX elementů

Podobně jako při práci s HTML tu a tam nastane chvíle, kdy potřebujeme změnit individuální CSS styl na nějakém prvku. V JSX k tomu také použijeme prop jménem style. Obsahem však musí být JavaScriptový objekt, kde jednotlivé CSS vlastnosti mají jména v camel case formátu. Takto například v Reactu nastavíme barvu pozadí, barvu písma a výšku elementu.

<div style={{ height: '5rem', color: 'white', backgroundColor: '#ff0000' }} />

Všimněte si, že zde narážíme na situaci, kdy máme objekt, jako hodnota pro nějakou prop. Je proto třeba dát si dobrý pozor na složené závorky. Takovýto kód nám fungovat nebude.

<div style={ height: '5rem', color: 'white', backgroundColor: '#ff0000' } />

Druhý důležitý fakt je, že všechny hodnoty pro naše styly musí být řetězce. Proto nám rozhodně nebude fungovat například takovýto kód.

<div style={{ height: 5rem, color: white, backgroundColor: #ff0000 }} />

Naopak co si snadno dovolit můžeme, je nastavit hodnotu stylu pomocí podmíněného operátoru.

<div
  style={{
    height: '5rem',
    color: 'white',
    backgroundColor: podminka ? '#ff0000' : '#0000ff',
  }}
/>

Podmíněné zobrazení.

Do této chvíle jsme na základě vstupních props komponenty měnili pouze její stylování. Často však narazíme na situaci, kdy chceme změnit i samotný obsah komponenty. Představme si, že máme například komponentu Product, která umožňuje objednat vložit produkt v e-shopu do košíku.

const Product = (props) => {
  return (
    <div className="product">
      <div className="product__name">{props.name}</div>
      <img className="product__img" src={props.img} />
      <button>Vložit do košíku</button>
    </div>
  );
};

Pokud už je však produkt objednaný, chtěli bychom zobrazit tlačítko s jiným nápisem. K tomuto můžeme s výhodou právě náš oblíbený podmíněný operátor.

const Product = (props) => {
  return (
    <div className="product">
      <div className="product__name">{props.name}</div>
      <img className="product__img" src={props.img} />
      {
        props.ordered ? <button>Zrušit objednávku</button> : <button>Vložit do košíku</button>
      }
    </div>
  );
};

Všimněte si, že na místě, kde chceme provést rozhodnutí, otevřeme pomocí složených závorek JavaScriptové okno, abychom mohli použít náš podmíněný operátor. Ten pak dle hodnoty uložné v prop s názvem ordered vrátí příslušný kus JSX.

Pokud v podmíněném operátoru pracujeme s obsáhlejším JSX, často se nám celý výraz nevejde na jeden řádek. Pak je ve zvyku formátovat kód komponenty takto.

const Product = (props) => {
  return (
    <div className="product">
      <div className="product__name">{props.name}</div>
      <img className="product__img" src={props.img} />
      {props.ordered ? (
        <button>Zrušit objednávku</button>
      ) : (
        <button>Vložit do košíku</button>
      )}
    </div>
  );
};

Občas se nám stane, že v jednom z případů podmínky nechcem zobrazit nic. Dejme tomu, že nechceme uživateli umožnit zrušit objednávku přímo u daného produktu. V takovém případě můžeme vrátit hodnotu null, která pro React znamená, že nemá zobrazit nic.

const Product = (props) => {
  return (
    <div className="product">
      <div className="product__name">{props.name}</div>
      <img className="product__img" src={props.img} />
      {props.ordered ? null : <button>Vložit do košíku</button>}
    </div>
  );
};

Cvičení: Podmíněné zobrazování

3

Mejlík - schránka

to dáš

V tomto cvičení vytvoříme základ komponenty pro zobrazování příchozí e-mailové pošty v naší nové aplikaci jménem Mejlík.cz.

  1. Založte si React projekt dle šablony z předchozí lekce.

  2. Vytvořte komponentu Inbox, která se použije takto.

    <Inbox account="radovan.holatko@mejlik.cz" messages={5} />
    

    Komponenta bude zobrazovat e-mail uživatele a počet jeho nepřečtených zpráv. Komponentu nastylujte dle následujícího vzoru

    Schránka

  3. Použijte v komponentě podmíněný operátor tak, aby zobrazila jinou zprávu v případě, že nepřečtených zpráv je nula.

    Schránka

  4. Použijte atribut style k tomu, abyste text o nepřečtených zprávách zobrazili červeně, pokud nemáme žádné nepřečtené zprávy.

4

Mejlík - hlavička

to dáš

Navážeme na předchozí cvičení a vytvořím komponentu pro hlavičku naší aplikace.

  1. Pokračujte v React projektu z předchozího cvičení.

  2. Stáhněte si vzor stránky. Najdete v něm nastylované dvě verze hlavičky pro naši aplikaci. Pozor, že tyto soubory slouží pouze jako vzor. Připravené CSS styly můžete rovnou použít jako základ pro to, jak má hlavička v naší aplikaci vypadat. Soubor index.html však do svého React projektu nekopírujte. React projekty mají svůj vlastní index.html, který má předem danou strukturu.

  3. Uvnitř vašeho React projektu založte komponentu Header, která bude žít ve vlastní složce. Bude představovat hlavičku stránky. Jak napsat její JSX můžete okouknout ze vzorového index.html.

  4. CSS komponenty používá dva obrázky. Nezapomeňte je vložit do složky img uvnitř složky Header.

  5. Chceme zařídit, že pokud je komponenta použita takto

    <Header user="Radovan Holátko" />
    

    zobrazí se hlavičku s přihlášeným uživatelem. Pokud je naopak použita takto

    <Header />
    

    zobrazí se hlavička nabízející přihlášení. Pokud jsme prop při použití komponenty nedali žádnou hodnotu, znamená to, že obsahuje hodnotu undefined.